Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
bb8059f6
Commit
bb8059f6
authored
Jul 26, 2016
by
Bas van Kervel
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core: ensure the canonical block is written before the canonical hash is set
parent
4c2cc32f
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
69 additions
and
20 deletions
+69
-20
blockchain.go
core/blockchain.go
+9
-9
blockchain_test.go
core/blockchain_test.go
+38
-0
database_util.go
core/database_util.go
+5
-1
headerchain.go
core/headerchain.go
+11
-7
filter.go
eth/filters/filter.go
+6
-3
No files found.
core/blockchain.go
View file @
bb8059f6
...
@@ -778,6 +778,14 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
...
@@ -778,6 +778,14 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
localTd
:=
self
.
GetTd
(
self
.
currentBlock
.
Hash
(),
self
.
currentBlock
.
NumberU64
())
localTd
:=
self
.
GetTd
(
self
.
currentBlock
.
Hash
(),
self
.
currentBlock
.
NumberU64
())
externTd
:=
new
(
big
.
Int
)
.
Add
(
block
.
Difficulty
(),
ptd
)
externTd
:=
new
(
big
.
Int
)
.
Add
(
block
.
Difficulty
(),
ptd
)
// Irrelevant of the canonical status, write the block itself to the database
if
err
:=
self
.
hc
.
WriteTd
(
block
.
Hash
(),
block
.
NumberU64
(),
externTd
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to write block total difficulty: %v"
,
err
)
}
if
err
:=
WriteBlock
(
self
.
chainDb
,
block
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to write block contents: %v"
,
err
)
}
// If the total difficulty is higher than our known, add it to the canonical chain
// If the total difficulty is higher than our known, add it to the canonical chain
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
...
@@ -788,19 +796,11 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
...
@@ -788,19 +796,11 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
return
NonStatTy
,
err
return
NonStatTy
,
err
}
}
}
}
// Insert the block as the new head of the chain
self
.
insert
(
block
)
// Insert the block as the new head of the chain
self
.
insert
(
block
)
status
=
CanonStatTy
status
=
CanonStatTy
}
else
{
}
else
{
status
=
SideStatTy
status
=
SideStatTy
}
}
// Irrelevant of the canonical status, write the block itself to the database
if
err
:=
self
.
hc
.
WriteTd
(
block
.
Hash
(),
block
.
NumberU64
(),
externTd
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to write block total difficulty: %v"
,
err
)
}
if
err
:=
WriteBlock
(
self
.
chainDb
,
block
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to write block contents: %v"
,
err
)
}
self
.
futureBlocks
.
Remove
(
block
.
Hash
())
self
.
futureBlocks
.
Remove
(
block
.
Hash
())
...
...
core/blockchain_test.go
View file @
bb8059f6
...
@@ -1090,3 +1090,41 @@ done:
...
@@ -1090,3 +1090,41 @@ done:
}
}
}
}
// Tests if the canonical block can be fetched from the database during chain insertion.
func
TestCanonicalBlockRetrieval
(
t
*
testing
.
T
)
{
var
(
db
,
_
=
ethdb
.
NewMemDatabase
()
genesis
=
WriteGenesisBlockForTesting
(
db
)
)
evmux
:=
&
event
.
TypeMux
{}
blockchain
,
_
:=
NewBlockChain
(
db
,
testChainConfig
(),
FakePow
{},
evmux
)
chain
,
_
:=
GenerateChain
(
nil
,
genesis
,
db
,
10
,
func
(
i
int
,
gen
*
BlockGen
)
{})
for
i
,
_
:=
range
chain
{
go
func
(
block
*
types
.
Block
)
{
// try to retrieve a block by its canonical hash and see if the block data can be retrieved.
for
{
ch
:=
GetCanonicalHash
(
db
,
block
.
NumberU64
())
if
ch
==
(
common
.
Hash
{})
{
continue
// busy wait for canonical hash to be written
}
if
ch
!=
block
.
Hash
()
{
t
.
Fatalf
(
"unknown canonical hash, want %s, got %s"
,
block
.
Hash
()
.
Hex
(),
ch
.
Hex
())
}
fb
:=
GetBlock
(
db
,
ch
,
block
.
NumberU64
())
if
fb
==
nil
{
t
.
Fatalf
(
"unable to retrieve block %d for canonical hash: %s"
,
block
.
NumberU64
(),
ch
.
Hex
())
}
if
fb
.
Hash
()
!=
block
.
Hash
()
{
t
.
Fatalf
(
"invalid block hash for block %d, want %s, got %s"
,
block
.
NumberU64
(),
block
.
Hash
()
.
Hex
(),
fb
.
Hash
()
.
Hex
())
}
return
}
}(
chain
[
i
])
blockchain
.
InsertChain
(
types
.
Blocks
{
chain
[
i
]})
}
}
core/database_util.go
View file @
bb8059f6
...
@@ -204,7 +204,11 @@ func GetTd(db ethdb.Database, hash common.Hash, number uint64) *big.Int {
...
@@ -204,7 +204,11 @@ func GetTd(db ethdb.Database, hash common.Hash, number uint64) *big.Int {
}
}
// GetBlock retrieves an entire block corresponding to the hash, assembling it
// GetBlock retrieves an entire block corresponding to the hash, assembling it
// back from the stored header and body.
// back from the stored header and body. If either the header or body could not
// be retrieved nil is returned.
//
// Note, due to concurrent download of header and block body the header and thus
// canonical hash can be stored in the database but the body data not (yet).
func
GetBlock
(
db
ethdb
.
Database
,
hash
common
.
Hash
,
number
uint64
)
*
types
.
Block
{
func
GetBlock
(
db
ethdb
.
Database
,
hash
common
.
Hash
,
number
uint64
)
*
types
.
Block
{
// Retrieve the block header and body contents
// Retrieve the block header and body contents
header
:=
GetHeader
(
db
,
hash
,
number
)
header
:=
GetHeader
(
db
,
hash
,
number
)
...
...
core/headerchain.go
View file @
bb8059f6
...
@@ -151,6 +151,14 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
...
@@ -151,6 +151,14 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
localTd
:=
hc
.
GetTd
(
hc
.
currentHeaderHash
,
hc
.
currentHeader
.
Number
.
Uint64
())
localTd
:=
hc
.
GetTd
(
hc
.
currentHeaderHash
,
hc
.
currentHeader
.
Number
.
Uint64
())
externTd
:=
new
(
big
.
Int
)
.
Add
(
header
.
Difficulty
,
ptd
)
externTd
:=
new
(
big
.
Int
)
.
Add
(
header
.
Difficulty
,
ptd
)
// Irrelevant of the canonical status, write the td and header to the database
if
err
:=
hc
.
WriteTd
(
hash
,
number
,
externTd
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to write header total difficulty: %v"
,
err
)
}
if
err
:=
WriteHeader
(
hc
.
chainDb
,
header
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to write header contents: %v"
,
err
)
}
// If the total difficulty is higher than our known, add it to the canonical chain
// If the total difficulty is higher than our known, add it to the canonical chain
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Second clause in the if statement reduces the vulnerability to selfish mining.
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
// Please refer to http://www.cs.cornell.edu/~ie53/publications/btcProcFC.pdf
...
@@ -176,6 +184,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
...
@@ -176,6 +184,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
headNumber
=
headHeader
.
Number
.
Uint64
()
-
1
headNumber
=
headHeader
.
Number
.
Uint64
()
-
1
headHeader
=
hc
.
GetHeader
(
headHash
,
headNumber
)
headHeader
=
hc
.
GetHeader
(
headHash
,
headNumber
)
}
}
// Extend the canonical chain with the new header
// Extend the canonical chain with the new header
if
err
:=
WriteCanonicalHash
(
hc
.
chainDb
,
hash
,
number
);
err
!=
nil
{
if
err
:=
WriteCanonicalHash
(
hc
.
chainDb
,
hash
,
number
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to insert header number: %v"
,
err
)
glog
.
Fatalf
(
"failed to insert header number: %v"
,
err
)
...
@@ -183,19 +192,14 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
...
@@ -183,19 +192,14 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
if
err
:=
WriteHeadHeaderHash
(
hc
.
chainDb
,
hash
);
err
!=
nil
{
if
err
:=
WriteHeadHeaderHash
(
hc
.
chainDb
,
hash
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to insert head header hash: %v"
,
err
)
glog
.
Fatalf
(
"failed to insert head header hash: %v"
,
err
)
}
}
hc
.
currentHeaderHash
,
hc
.
currentHeader
=
hash
,
types
.
CopyHeader
(
header
)
hc
.
currentHeaderHash
,
hc
.
currentHeader
=
hash
,
types
.
CopyHeader
(
header
)
status
=
CanonStatTy
status
=
CanonStatTy
}
else
{
}
else
{
status
=
SideStatTy
status
=
SideStatTy
}
}
// Irrelevant of the canonical status, write the header itself to the database
if
err
:=
hc
.
WriteTd
(
hash
,
number
,
externTd
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to write header total difficulty: %v"
,
err
)
}
if
err
:=
WriteHeader
(
hc
.
chainDb
,
header
);
err
!=
nil
{
glog
.
Fatalf
(
"failed to write header contents: %v"
,
err
)
}
hc
.
headerCache
.
Add
(
hash
,
header
)
hc
.
headerCache
.
Add
(
hash
,
header
)
hc
.
numberCache
.
Add
(
hash
,
number
)
hc
.
numberCache
.
Add
(
hash
,
number
)
...
...
eth/filters/filter.go
View file @
bb8059f6
...
@@ -74,6 +74,9 @@ func (self *Filter) SetTopics(topics [][]common.Hash) {
...
@@ -74,6 +74,9 @@ func (self *Filter) SetTopics(topics [][]common.Hash) {
func
(
self
*
Filter
)
Find
()
vm
.
Logs
{
func
(
self
*
Filter
)
Find
()
vm
.
Logs
{
latestHash
:=
core
.
GetHeadBlockHash
(
self
.
db
)
latestHash
:=
core
.
GetHeadBlockHash
(
self
.
db
)
latestBlock
:=
core
.
GetBlock
(
self
.
db
,
latestHash
,
core
.
GetBlockNumber
(
self
.
db
,
latestHash
))
latestBlock
:=
core
.
GetBlock
(
self
.
db
,
latestHash
,
core
.
GetBlockNumber
(
self
.
db
,
latestHash
))
if
latestBlock
==
nil
{
return
vm
.
Logs
{}
}
var
beginBlockNo
uint64
=
uint64
(
self
.
begin
)
var
beginBlockNo
uint64
=
uint64
(
self
.
begin
)
if
self
.
begin
==
-
1
{
if
self
.
begin
==
-
1
{
beginBlockNo
=
latestBlock
.
NumberU64
()
beginBlockNo
=
latestBlock
.
NumberU64
()
...
@@ -123,13 +126,13 @@ func (self *Filter) mipFind(start, end uint64, depth int) (logs vm.Logs) {
...
@@ -123,13 +126,13 @@ func (self *Filter) mipFind(start, end uint64, depth int) (logs vm.Logs) {
}
}
func
(
self
*
Filter
)
getLogs
(
start
,
end
uint64
)
(
logs
vm
.
Logs
)
{
func
(
self
*
Filter
)
getLogs
(
start
,
end
uint64
)
(
logs
vm
.
Logs
)
{
var
block
*
types
.
Block
for
i
:=
start
;
i
<=
end
;
i
++
{
for
i
:=
start
;
i
<=
end
;
i
++
{
var
block
*
types
.
Block
hash
:=
core
.
GetCanonicalHash
(
self
.
db
,
i
)
hash
:=
core
.
GetCanonicalHash
(
self
.
db
,
i
)
if
hash
!=
(
common
.
Hash
{})
{
if
hash
!=
(
common
.
Hash
{})
{
block
=
core
.
GetBlock
(
self
.
db
,
hash
,
i
)
block
=
core
.
GetBlock
(
self
.
db
,
hash
,
i
)
}
else
{
// block not found
}
if
block
==
nil
{
// block not found/written
return
logs
return
logs
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment