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
accc0fab
Unverified
Commit
accc0fab
authored
Nov 16, 2018
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
core, eth/downloader: fix ancestor lookup for fast sync
parent
51b2f162
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
70 additions
and
15 deletions
+70
-15
blockchain.go
core/blockchain.go
+11
-2
accessors_chain.go
core/rawdb/accessors_chain.go
+9
-0
downloader.go
eth/downloader/downloader.go
+29
-4
downloader_test.go
eth/downloader/downloader_test.go
+21
-9
No files found.
core/blockchain.go
View file @
accc0fab
...
@@ -561,6 +561,17 @@ func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
...
@@ -561,6 +561,17 @@ func (bc *BlockChain) HasBlock(hash common.Hash, number uint64) bool {
return
rawdb
.
HasBody
(
bc
.
db
,
hash
,
number
)
return
rawdb
.
HasBody
(
bc
.
db
,
hash
,
number
)
}
}
// HasFastBlock checks if a fast block is fully present in the database or not.
func
(
bc
*
BlockChain
)
HasFastBlock
(
hash
common
.
Hash
,
number
uint64
)
bool
{
if
!
bc
.
HasBlock
(
hash
,
number
)
{
return
false
}
if
bc
.
receiptsCache
.
Contains
(
hash
)
{
return
true
}
return
rawdb
.
HasReceipts
(
bc
.
db
,
hash
,
number
)
}
// HasState checks if state trie is fully present in the database or not.
// HasState checks if state trie is fully present in the database or not.
func
(
bc
*
BlockChain
)
HasState
(
hash
common
.
Hash
)
bool
{
func
(
bc
*
BlockChain
)
HasState
(
hash
common
.
Hash
)
bool
{
_
,
err
:=
bc
.
stateCache
.
OpenTrie
(
hash
)
_
,
err
:=
bc
.
stateCache
.
OpenTrie
(
hash
)
...
@@ -618,12 +629,10 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
...
@@ -618,12 +629,10 @@ func (bc *BlockChain) GetReceiptsByHash(hash common.Hash) types.Receipts {
if
receipts
,
ok
:=
bc
.
receiptsCache
.
Get
(
hash
);
ok
{
if
receipts
,
ok
:=
bc
.
receiptsCache
.
Get
(
hash
);
ok
{
return
receipts
.
(
types
.
Receipts
)
return
receipts
.
(
types
.
Receipts
)
}
}
number
:=
rawdb
.
ReadHeaderNumber
(
bc
.
db
,
hash
)
number
:=
rawdb
.
ReadHeaderNumber
(
bc
.
db
,
hash
)
if
number
==
nil
{
if
number
==
nil
{
return
nil
return
nil
}
}
receipts
:=
rawdb
.
ReadReceipts
(
bc
.
db
,
hash
,
*
number
)
receipts
:=
rawdb
.
ReadReceipts
(
bc
.
db
,
hash
,
*
number
)
bc
.
receiptsCache
.
Add
(
hash
,
receipts
)
bc
.
receiptsCache
.
Add
(
hash
,
receipts
)
return
receipts
return
receipts
...
...
core/rawdb/accessors_chain.go
View file @
accc0fab
...
@@ -271,6 +271,15 @@ func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) {
...
@@ -271,6 +271,15 @@ func DeleteTd(db DatabaseDeleter, hash common.Hash, number uint64) {
}
}
}
}
// HasReceipts verifies the existence of all the transaction receipts belonging
// to a block.
func
HasReceipts
(
db
DatabaseReader
,
hash
common
.
Hash
,
number
uint64
)
bool
{
if
has
,
err
:=
db
.
Has
(
blockReceiptsKey
(
number
,
hash
));
!
has
||
err
!=
nil
{
return
false
}
return
true
}
// ReadReceipts retrieves all the transaction receipts belonging to a block.
// ReadReceipts retrieves all the transaction receipts belonging to a block.
func
ReadReceipts
(
db
DatabaseReader
,
hash
common
.
Hash
,
number
uint64
)
types
.
Receipts
{
func
ReadReceipts
(
db
DatabaseReader
,
hash
common
.
Hash
,
number
uint64
)
types
.
Receipts
{
// Retrieve the flattened receipt slice
// Retrieve the flattened receipt slice
...
...
eth/downloader/downloader.go
View file @
accc0fab
...
@@ -181,6 +181,9 @@ type BlockChain interface {
...
@@ -181,6 +181,9 @@ type BlockChain interface {
// HasBlock verifies a block's presence in the local chain.
// HasBlock verifies a block's presence in the local chain.
HasBlock
(
common
.
Hash
,
uint64
)
bool
HasBlock
(
common
.
Hash
,
uint64
)
bool
// HasFastBlock verifies a fast block's presence in the local chain.
HasFastBlock
(
common
.
Hash
,
uint64
)
bool
// GetBlockByHash retrieves a block from the local chain.
// GetBlockByHash retrieves a block from the local chain.
GetBlockByHash
(
common
.
Hash
)
*
types
.
Block
GetBlockByHash
(
common
.
Hash
)
*
types
.
Block
...
@@ -663,8 +666,9 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
...
@@ -663,8 +666,9 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
if
localHeight
>=
MaxForkAncestry
{
if
localHeight
>=
MaxForkAncestry
{
floor
=
int64
(
localHeight
-
MaxForkAncestry
)
floor
=
int64
(
localHeight
-
MaxForkAncestry
)
}
}
from
,
count
,
skip
,
max
:=
calculateRequestSpan
(
remoteHeight
,
localHeight
)
from
,
count
,
skip
,
max
:=
calculateRequestSpan
(
remoteHeight
,
localHeight
)
p
.
log
.
Trace
(
"Span searching for common ancestor"
,
"count"
,
count
,
"from"
,
from
,
"skip"
,
skip
)
go
p
.
peer
.
RequestHeadersByNumber
(
uint64
(
from
),
count
,
skip
,
false
)
go
p
.
peer
.
RequestHeadersByNumber
(
uint64
(
from
),
count
,
skip
,
false
)
// Wait for the remote response to the head fetch
// Wait for the remote response to the head fetch
...
@@ -708,8 +712,17 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
...
@@ -708,8 +712,17 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
// Otherwise check if we already know the header or not
// Otherwise check if we already know the header or not
h
:=
headers
[
i
]
.
Hash
()
h
:=
headers
[
i
]
.
Hash
()
n
:=
headers
[
i
]
.
Number
.
Uint64
()
n
:=
headers
[
i
]
.
Number
.
Uint64
()
if
(
d
.
mode
==
FullSync
&&
d
.
blockchain
.
HasBlock
(
h
,
n
))
||
(
d
.
mode
!=
FullSync
&&
d
.
lightchain
.
HasHeader
(
h
,
n
))
{
var
known
bool
switch
d
.
mode
{
case
FullSync
:
known
=
d
.
blockchain
.
HasBlock
(
h
,
n
)
case
FastSync
:
known
=
d
.
blockchain
.
HasFastBlock
(
h
,
n
)
default
:
known
=
d
.
lightchain
.
HasHeader
(
h
,
n
)
}
if
known
{
number
,
hash
=
n
,
h
number
,
hash
=
n
,
h
break
break
}
}
...
@@ -738,6 +751,8 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
...
@@ -738,6 +751,8 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
if
floor
>
0
{
if
floor
>
0
{
start
=
uint64
(
floor
)
start
=
uint64
(
floor
)
}
}
p
.
log
.
Trace
(
"Binary searching for common ancestor"
,
"start"
,
start
,
"end"
,
end
)
for
start
+
1
<
end
{
for
start
+
1
<
end
{
// Split our chain interval in two, and request the hash to cross check
// Split our chain interval in two, and request the hash to cross check
check
:=
(
start
+
end
)
/
2
check
:=
(
start
+
end
)
/
2
...
@@ -770,7 +785,17 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
...
@@ -770,7 +785,17 @@ func (d *Downloader) findAncestor(p *peerConnection, remoteHeader *types.Header)
// Modify the search interval based on the response
// Modify the search interval based on the response
h
:=
headers
[
0
]
.
Hash
()
h
:=
headers
[
0
]
.
Hash
()
n
:=
headers
[
0
]
.
Number
.
Uint64
()
n
:=
headers
[
0
]
.
Number
.
Uint64
()
if
(
d
.
mode
==
FullSync
&&
!
d
.
blockchain
.
HasBlock
(
h
,
n
))
||
(
d
.
mode
!=
FullSync
&&
!
d
.
lightchain
.
HasHeader
(
h
,
n
))
{
var
known
bool
switch
d
.
mode
{
case
FullSync
:
known
=
d
.
blockchain
.
HasBlock
(
h
,
n
)
case
FastSync
:
known
=
d
.
blockchain
.
HasFastBlock
(
h
,
n
)
default
:
known
=
d
.
lightchain
.
HasHeader
(
h
,
n
)
}
if
!
known
{
end
=
check
end
=
check
break
break
}
}
...
...
eth/downloader/downloader_test.go
View file @
accc0fab
...
@@ -115,6 +115,15 @@ func (dl *downloadTester) HasBlock(hash common.Hash, number uint64) bool {
...
@@ -115,6 +115,15 @@ func (dl *downloadTester) HasBlock(hash common.Hash, number uint64) bool {
return
dl
.
GetBlockByHash
(
hash
)
!=
nil
return
dl
.
GetBlockByHash
(
hash
)
!=
nil
}
}
// HasFastBlock checks if a block is present in the testers canonical chain.
func
(
dl
*
downloadTester
)
HasFastBlock
(
hash
common
.
Hash
,
number
uint64
)
bool
{
dl
.
lock
.
RLock
()
defer
dl
.
lock
.
RUnlock
()
_
,
ok
:=
dl
.
ownReceipts
[
hash
]
return
ok
}
// GetHeader retrieves a header from the testers canonical chain.
// GetHeader retrieves a header from the testers canonical chain.
func
(
dl
*
downloadTester
)
GetHeaderByHash
(
hash
common
.
Hash
)
*
types
.
Header
{
func
(
dl
*
downloadTester
)
GetHeaderByHash
(
hash
common
.
Hash
)
*
types
.
Header
{
dl
.
lock
.
RLock
()
dl
.
lock
.
RLock
()
...
@@ -235,6 +244,7 @@ func (dl *downloadTester) InsertChain(blocks types.Blocks) (i int, err error) {
...
@@ -235,6 +244,7 @@ func (dl *downloadTester) InsertChain(blocks types.Blocks) (i int, err error) {
dl
.
ownHeaders
[
block
.
Hash
()]
=
block
.
Header
()
dl
.
ownHeaders
[
block
.
Hash
()]
=
block
.
Header
()
}
}
dl
.
ownBlocks
[
block
.
Hash
()]
=
block
dl
.
ownBlocks
[
block
.
Hash
()]
=
block
dl
.
ownReceipts
[
block
.
Hash
()]
=
make
(
types
.
Receipts
,
0
)
dl
.
stateDb
.
Put
(
block
.
Root
()
.
Bytes
(),
[]
byte
{
0x00
})
dl
.
stateDb
.
Put
(
block
.
Root
()
.
Bytes
(),
[]
byte
{
0x00
})
dl
.
ownChainTd
[
block
.
Hash
()]
=
new
(
big
.
Int
)
.
Add
(
dl
.
ownChainTd
[
block
.
ParentHash
()],
block
.
Difficulty
())
dl
.
ownChainTd
[
block
.
Hash
()]
=
new
(
big
.
Int
)
.
Add
(
dl
.
ownChainTd
[
block
.
ParentHash
()],
block
.
Difficulty
())
}
}
...
@@ -375,28 +385,28 @@ func (dlp *downloadTesterPeer) RequestNodeData(hashes []common.Hash) error {
...
@@ -375,28 +385,28 @@ func (dlp *downloadTesterPeer) RequestNodeData(hashes []common.Hash) error {
// assertOwnChain checks if the local chain contains the correct number of items
// assertOwnChain checks if the local chain contains the correct number of items
// of the various chain components.
// of the various chain components.
func
assertOwnChain
(
t
*
testing
.
T
,
tester
*
downloadTester
,
length
int
)
{
func
assertOwnChain
(
t
*
testing
.
T
,
tester
*
downloadTester
,
length
int
)
{
// Mark this method as a helper to report errors at callsite, not in here
t
.
Helper
()
assertOwnForkedChain
(
t
,
tester
,
1
,
[]
int
{
length
})
assertOwnForkedChain
(
t
,
tester
,
1
,
[]
int
{
length
})
}
}
// assertOwnForkedChain checks if the local forked chain contains the correct
// assertOwnForkedChain checks if the local forked chain contains the correct
// number of items of the various chain components.
// number of items of the various chain components.
func
assertOwnForkedChain
(
t
*
testing
.
T
,
tester
*
downloadTester
,
common
int
,
lengths
[]
int
)
{
func
assertOwnForkedChain
(
t
*
testing
.
T
,
tester
*
downloadTester
,
common
int
,
lengths
[]
int
)
{
// Mark this method as a helper to report errors at callsite, not in here
t
.
Helper
()
// Initialize the counters for the first fork
// Initialize the counters for the first fork
headers
,
blocks
,
receipts
:=
lengths
[
0
],
lengths
[
0
],
lengths
[
0
]
-
fsMinFullBlocks
headers
,
blocks
,
receipts
:=
lengths
[
0
],
lengths
[
0
],
lengths
[
0
]
if
receipts
<
0
{
receipts
=
1
}
// Update the counters for each subsequent fork
// Update the counters for each subsequent fork
for
_
,
length
:=
range
lengths
[
1
:
]
{
for
_
,
length
:=
range
lengths
[
1
:
]
{
headers
+=
length
-
common
headers
+=
length
-
common
blocks
+=
length
-
common
blocks
+=
length
-
common
receipts
+=
length
-
common
-
fsMinFullBlocks
receipts
+=
length
-
common
}
}
switch
tester
.
downloader
.
mode
{
if
tester
.
downloader
.
mode
==
LightSync
{
case
FullSync
:
receipts
=
1
case
LightSync
:
blocks
,
receipts
=
1
,
1
blocks
,
receipts
=
1
,
1
}
}
if
hs
:=
len
(
tester
.
ownHeaders
);
hs
!=
headers
{
if
hs
:=
len
(
tester
.
ownHeaders
);
hs
!=
headers
{
...
@@ -1150,7 +1160,9 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) {
...
@@ -1150,7 +1160,9 @@ func testSyncProgress(t *testing.T, protocol int, mode SyncMode) {
}
}
func
checkProgress
(
t
*
testing
.
T
,
d
*
Downloader
,
stage
string
,
want
ethereum
.
SyncProgress
)
{
func
checkProgress
(
t
*
testing
.
T
,
d
*
Downloader
,
stage
string
,
want
ethereum
.
SyncProgress
)
{
// Mark this method as a helper to report errors at callsite, not in here
t
.
Helper
()
t
.
Helper
()
p
:=
d
.
Progress
()
p
:=
d
.
Progress
()
p
.
KnownStates
,
p
.
PulledStates
=
0
,
0
p
.
KnownStates
,
p
.
PulledStates
=
0
,
0
want
.
KnownStates
,
want
.
PulledStates
=
0
,
0
want
.
KnownStates
,
want
.
PulledStates
=
0
,
0
...
...
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