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
6adbaabc
You need to sign in or sign up before continuing.
Commit
6adbaabc
authored
Jul 29, 2015
by
Péter Szilágyi
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
eth, eth/downloader: don't report stall if fetcher filled the block
parent
cc27be9d
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
65 additions
and
43 deletions
+65
-43
downloader.go
eth/downloader/downloader.go
+22
-10
downloader_test.go
eth/downloader/downloader_test.go
+42
-32
sync.go
eth/sync.go
+1
-1
No files found.
eth/downloader/downloader.go
View file @
6adbaabc
...
@@ -21,6 +21,7 @@ import (
...
@@ -21,6 +21,7 @@ import (
"bytes"
"bytes"
"errors"
"errors"
"math"
"math"
"math/big"
"math/rand"
"math/rand"
"sync"
"sync"
"sync/atomic"
"sync/atomic"
...
@@ -232,10 +233,10 @@ func (d *Downloader) UnregisterPeer(id string) error {
...
@@ -232,10 +233,10 @@ func (d *Downloader) UnregisterPeer(id string) error {
// Synchronise tries to sync up our local block chain with a remote peer, both
// Synchronise tries to sync up our local block chain with a remote peer, both
// adding various sanity checks as well as wrapping it with various log entries.
// adding various sanity checks as well as wrapping it with various log entries.
func
(
d
*
Downloader
)
Synchronise
(
id
string
,
head
common
.
Hash
)
{
func
(
d
*
Downloader
)
Synchronise
(
id
string
,
head
common
.
Hash
,
td
*
big
.
Int
)
{
glog
.
V
(
logger
.
Detail
)
.
Infof
(
"Attempting synchronisation: %v,
0x%x"
,
id
,
hea
d
)
glog
.
V
(
logger
.
Detail
)
.
Infof
(
"Attempting synchronisation: %v,
head 0x%x, TD %v"
,
id
,
head
[
:
4
],
t
d
)
switch
err
:=
d
.
synchronise
(
id
,
head
);
err
{
switch
err
:=
d
.
synchronise
(
id
,
head
,
td
);
err
{
case
nil
:
case
nil
:
glog
.
V
(
logger
.
Detail
)
.
Infof
(
"Synchronisation completed"
)
glog
.
V
(
logger
.
Detail
)
.
Infof
(
"Synchronisation completed"
)
...
@@ -257,7 +258,7 @@ func (d *Downloader) Synchronise(id string, head common.Hash) {
...
@@ -257,7 +258,7 @@ func (d *Downloader) Synchronise(id string, head common.Hash) {
// synchronise will select the peer and use it for synchronising. If an empty string is given
// synchronise will select the peer and use it for synchronising. If an empty string is given
// it will use the best peer possible and synchronize if it's TD is higher than our own. If any of the
// it will use the best peer possible and synchronize if it's TD is higher than our own. If any of the
// checks fail an error will be returned. This method is synchronous
// checks fail an error will be returned. This method is synchronous
func
(
d
*
Downloader
)
synchronise
(
id
string
,
hash
common
.
Hash
)
error
{
func
(
d
*
Downloader
)
synchronise
(
id
string
,
hash
common
.
Hash
,
td
*
big
.
Int
)
error
{
// Mock out the synchonisation if testing
// Mock out the synchonisation if testing
if
d
.
synchroniseMock
!=
nil
{
if
d
.
synchroniseMock
!=
nil
{
return
d
.
synchroniseMock
(
id
,
hash
)
return
d
.
synchroniseMock
(
id
,
hash
)
...
@@ -295,7 +296,7 @@ func (d *Downloader) synchronise(id string, hash common.Hash) error {
...
@@ -295,7 +296,7 @@ func (d *Downloader) synchronise(id string, hash common.Hash) error {
if
p
==
nil
{
if
p
==
nil
{
return
errUnknownPeer
return
errUnknownPeer
}
}
return
d
.
syncWithPeer
(
p
,
hash
)
return
d
.
syncWithPeer
(
p
,
hash
,
td
)
}
}
// Has checks if the downloader knows about a particular hash, meaning that its
// Has checks if the downloader knows about a particular hash, meaning that its
...
@@ -306,7 +307,7 @@ func (d *Downloader) Has(hash common.Hash) bool {
...
@@ -306,7 +307,7 @@ func (d *Downloader) Has(hash common.Hash) bool {
// syncWithPeer starts a block synchronization based on the hash chain from the
// syncWithPeer starts a block synchronization based on the hash chain from the
// specified peer and head hash.
// specified peer and head hash.
func
(
d
*
Downloader
)
syncWithPeer
(
p
*
peer
,
hash
common
.
Hash
)
(
err
error
)
{
func
(
d
*
Downloader
)
syncWithPeer
(
p
*
peer
,
hash
common
.
Hash
,
td
*
big
.
Int
)
(
err
error
)
{
d
.
mux
.
Post
(
StartEvent
{})
d
.
mux
.
Post
(
StartEvent
{})
defer
func
()
{
defer
func
()
{
// reset on error
// reset on error
...
@@ -335,7 +336,7 @@ func (d *Downloader) syncWithPeer(p *peer, hash common.Hash) (err error) {
...
@@ -335,7 +336,7 @@ func (d *Downloader) syncWithPeer(p *peer, hash common.Hash) (err error) {
return
err
return
err
}
}
errc
:=
make
(
chan
error
,
2
)
errc
:=
make
(
chan
error
,
2
)
go
func
()
{
errc
<-
d
.
fetchHashes
(
p
,
number
+
1
)
}()
go
func
()
{
errc
<-
d
.
fetchHashes
(
p
,
td
,
number
+
1
)
}()
go
func
()
{
errc
<-
d
.
fetchBlocks
(
number
+
1
)
}()
go
func
()
{
errc
<-
d
.
fetchBlocks
(
number
+
1
)
}()
// If any fetcher fails, cancel the other
// If any fetcher fails, cancel the other
...
@@ -788,7 +789,7 @@ func (d *Downloader) findAncestor(p *peer) (uint64, error) {
...
@@ -788,7 +789,7 @@ func (d *Downloader) findAncestor(p *peer) (uint64, error) {
// fetchHashes keeps retrieving hashes from the requested number, until no more
// fetchHashes keeps retrieving hashes from the requested number, until no more
// are returned, potentially throttling on the way.
// are returned, potentially throttling on the way.
func
(
d
*
Downloader
)
fetchHashes
(
p
*
peer
,
from
uint64
)
error
{
func
(
d
*
Downloader
)
fetchHashes
(
p
*
peer
,
td
*
big
.
Int
,
from
uint64
)
error
{
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"%v: downloading hashes from #%d"
,
p
,
from
)
glog
.
V
(
logger
.
Debug
)
.
Infof
(
"%v: downloading hashes from #%d"
,
p
,
from
)
// Create a timeout timer, and the associated hash fetcher
// Create a timeout timer, and the associated hash fetcher
...
@@ -827,8 +828,19 @@ func (d *Downloader) fetchHashes(p *peer, from uint64) error {
...
@@ -827,8 +828,19 @@ func (d *Downloader) fetchHashes(p *peer, from uint64) error {
case
d
.
processCh
<-
false
:
case
d
.
processCh
<-
false
:
case
<-
d
.
cancelCh
:
case
<-
d
.
cancelCh
:
}
}
// Error out if no hashes were retrieved at all
// If no hashes were retrieved at all, the peer violated it's TD promise that it had a
if
!
gotHashes
{
// better chain compared to ours. The only exception is if it's promised blocks were
// already imported by other means (e.g. fecher):
//
// R <remote peer>, L <local node>: Both at block 10
// R: Mine block 11, and propagate it to L
// L: Queue block 11 for import
// L: Notice that R's head and TD increased compared to ours, start sync
// L: Import of block 11 finishes
// L: Sync begins, and finds common ancestor at 11
// L: Request new hashes up from 11 (R's TD was higher, it must have something)
// R: Nothing to give
if
!
gotHashes
&&
td
.
Cmp
(
d
.
headBlock
()
.
Td
)
>
0
{
return
errStallingPeer
return
errStallingPeer
}
}
return
nil
return
nil
...
...
eth/downloader/downloader_test.go
View file @
6adbaabc
...
@@ -97,8 +97,18 @@ func newTester() *downloadTester {
...
@@ -97,8 +97,18 @@ func newTester() *downloadTester {
}
}
// sync starts synchronizing with a remote peer, blocking until it completes.
// sync starts synchronizing with a remote peer, blocking until it completes.
func
(
dl
*
downloadTester
)
sync
(
id
string
)
error
{
func
(
dl
*
downloadTester
)
sync
(
id
string
,
td
*
big
.
Int
)
error
{
err
:=
dl
.
downloader
.
synchronise
(
id
,
dl
.
peerHashes
[
id
][
0
])
hash
:=
dl
.
peerHashes
[
id
][
0
]
// If no particular TD was requested, load from the peer's blockchain
if
td
==
nil
{
td
=
big
.
NewInt
(
1
)
if
block
,
ok
:=
dl
.
peerBlocks
[
id
][
hash
];
ok
{
td
=
block
.
Td
}
}
err
:=
dl
.
downloader
.
synchronise
(
id
,
hash
,
td
)
for
{
for
{
// If the queue is empty and processing stopped, break
// If the queue is empty and processing stopped, break
hashes
,
blocks
:=
dl
.
downloader
.
queue
.
Size
()
hashes
,
blocks
:=
dl
.
downloader
.
queue
.
Size
()
...
@@ -261,7 +271,7 @@ func TestSynchronisation60(t *testing.T) {
...
@@ -261,7 +271,7 @@ func TestSynchronisation60(t *testing.T) {
tester
.
newPeer
(
"peer"
,
eth60
,
hashes
,
blocks
)
tester
.
newPeer
(
"peer"
,
eth60
,
hashes
,
blocks
)
// Synchronise with the peer and make sure all blocks were retrieved
// Synchronise with the peer and make sure all blocks were retrieved
if
err
:=
tester
.
sync
(
"peer"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"peer"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
targetBlocks
+
1
{
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
targetBlocks
+
1
{
...
@@ -281,7 +291,7 @@ func TestCanonicalSynchronisation61(t *testing.T) {
...
@@ -281,7 +291,7 @@ func TestCanonicalSynchronisation61(t *testing.T) {
tester
.
newPeer
(
"peer"
,
eth61
,
hashes
,
blocks
)
tester
.
newPeer
(
"peer"
,
eth61
,
hashes
,
blocks
)
// Synchronise with the peer and make sure all blocks were retrieved
// Synchronise with the peer and make sure all blocks were retrieved
if
err
:=
tester
.
sync
(
"peer"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"peer"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
targetBlocks
+
1
{
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
targetBlocks
+
1
{
...
@@ -312,7 +322,7 @@ func testThrottling(t *testing.T, protocol int) {
...
@@ -312,7 +322,7 @@ func testThrottling(t *testing.T, protocol int) {
// Start a synchronisation concurrently
// Start a synchronisation concurrently
errc
:=
make
(
chan
error
)
errc
:=
make
(
chan
error
)
go
func
()
{
go
func
()
{
errc
<-
tester
.
sync
(
"peer"
)
errc
<-
tester
.
sync
(
"peer"
,
nil
)
}()
}()
// Iteratively take some blocks, always checking the retrieval count
// Iteratively take some blocks, always checking the retrieval count
for
len
(
tester
.
ownBlocks
)
<
targetBlocks
+
1
{
for
len
(
tester
.
ownBlocks
)
<
targetBlocks
+
1
{
...
@@ -361,14 +371,14 @@ func TestForkedSynchronisation61(t *testing.T) {
...
@@ -361,14 +371,14 @@ func TestForkedSynchronisation61(t *testing.T) {
tester
.
newPeer
(
"fork B"
,
eth61
,
hashesB
,
blocksB
)
tester
.
newPeer
(
"fork B"
,
eth61
,
hashesB
,
blocksB
)
// Synchronise with the peer and make sure all blocks were retrieved
// Synchronise with the peer and make sure all blocks were retrieved
if
err
:=
tester
.
sync
(
"fork A"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"fork A"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
common
+
fork
+
1
{
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
common
+
fork
+
1
{
t
.
Fatalf
(
"synchronised block mismatch: have %v, want %v"
,
imported
,
common
+
fork
+
1
)
t
.
Fatalf
(
"synchronised block mismatch: have %v, want %v"
,
imported
,
common
+
fork
+
1
)
}
}
// Synchronise with the second peer and make sure that fork is pulled too
// Synchronise with the second peer and make sure that fork is pulled too
if
err
:=
tester
.
sync
(
"fork B"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"fork B"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
common
+
2
*
fork
+
1
{
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
common
+
2
*
fork
+
1
{
...
@@ -411,7 +421,7 @@ func testCancel(t *testing.T, protocol int) {
...
@@ -411,7 +421,7 @@ func testCancel(t *testing.T, protocol int) {
t
.
Errorf
(
"block or hash count mismatch: %d hashes, %d blocks, want 0"
,
hashCount
,
blockCount
)
t
.
Errorf
(
"block or hash count mismatch: %d hashes, %d blocks, want 0"
,
hashCount
,
blockCount
)
}
}
// Synchronise with the peer, but cancel afterwards
// Synchronise with the peer, but cancel afterwards
if
err
:=
tester
.
sync
(
"peer"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"peer"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
tester
.
downloader
.
cancel
()
tester
.
downloader
.
cancel
()
...
@@ -438,14 +448,14 @@ func testMultiSynchronisation(t *testing.T, protocol int) {
...
@@ -438,14 +448,14 @@ func testMultiSynchronisation(t *testing.T, protocol int) {
}
}
// Synchronise with the middle peer and make sure half of the blocks were retrieved
// Synchronise with the middle peer and make sure half of the blocks were retrieved
id
:=
fmt
.
Sprintf
(
"peer #%d"
,
targetPeers
/
2
)
id
:=
fmt
.
Sprintf
(
"peer #%d"
,
targetPeers
/
2
)
if
err
:=
tester
.
sync
(
id
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
id
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
len
(
tester
.
peerHashes
[
id
])
{
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
len
(
tester
.
peerHashes
[
id
])
{
t
.
Fatalf
(
"synchronised block mismatch: have %v, want %v"
,
imported
,
len
(
tester
.
peerHashes
[
id
]))
t
.
Fatalf
(
"synchronised block mismatch: have %v, want %v"
,
imported
,
len
(
tester
.
peerHashes
[
id
]))
}
}
// Synchronise with the best peer and make sure everything is retrieved
// Synchronise with the best peer and make sure everything is retrieved
if
err
:=
tester
.
sync
(
"peer #0"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"peer #0"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
targetBlocks
+
1
{
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
targetBlocks
+
1
{
...
@@ -469,7 +479,7 @@ func TestSlowSynchronisation60(t *testing.T) {
...
@@ -469,7 +479,7 @@ func TestSlowSynchronisation60(t *testing.T) {
// Try to sync with the peers (pull hashes from fast)
// Try to sync with the peers (pull hashes from fast)
start
:=
time
.
Now
()
start
:=
time
.
Now
()
if
err
:=
tester
.
sync
(
"fast"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"fast"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
targetBlocks
+
1
{
if
imported
:=
len
(
tester
.
ownBlocks
);
imported
!=
targetBlocks
+
1
{
...
@@ -497,14 +507,14 @@ func TestNonExistingParentAttack60(t *testing.T) {
...
@@ -497,14 +507,14 @@ func TestNonExistingParentAttack60(t *testing.T) {
tester
.
newPeer
(
"attack"
,
eth60
,
hashes
,
blocks
)
tester
.
newPeer
(
"attack"
,
eth60
,
hashes
,
blocks
)
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
if
err
:=
tester
.
sync
(
"attack"
);
err
==
nil
{
if
err
:=
tester
.
sync
(
"attack"
,
nil
);
err
==
nil
{
t
.
Fatalf
(
"block synchronization succeeded"
)
t
.
Fatalf
(
"block synchronization succeeded"
)
}
}
if
tester
.
hasBlock
(
hashes
[
0
])
{
if
tester
.
hasBlock
(
hashes
[
0
])
{
t
.
Fatalf
(
"tester accepted unknown-parent block: %v"
,
blocks
[
hashes
[
0
]])
t
.
Fatalf
(
"tester accepted unknown-parent block: %v"
,
blocks
[
hashes
[
0
]])
}
}
// Try to synchronize with the valid chain and make sure it succeeds
// Try to synchronize with the valid chain and make sure it succeeds
if
err
:=
tester
.
sync
(
"valid"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"valid"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
if
!
tester
.
hasBlock
(
tester
.
peerHashes
[
"valid"
][
0
])
{
if
!
tester
.
hasBlock
(
tester
.
peerHashes
[
"valid"
][
0
])
{
...
@@ -525,7 +535,7 @@ func TestRepeatingHashAttack60(t *testing.T) { // TODO: Is this thing valid??
...
@@ -525,7 +535,7 @@ func TestRepeatingHashAttack60(t *testing.T) { // TODO: Is this thing valid??
// Try and sync with the malicious node
// Try and sync with the malicious node
errc
:=
make
(
chan
error
)
errc
:=
make
(
chan
error
)
go
func
()
{
go
func
()
{
errc
<-
tester
.
sync
(
"attack"
)
errc
<-
tester
.
sync
(
"attack"
,
nil
)
}()
}()
// Make sure that syncing returns and does so with a failure
// Make sure that syncing returns and does so with a failure
select
{
select
{
...
@@ -537,7 +547,7 @@ func TestRepeatingHashAttack60(t *testing.T) { // TODO: Is this thing valid??
...
@@ -537,7 +547,7 @@ func TestRepeatingHashAttack60(t *testing.T) { // TODO: Is this thing valid??
}
}
}
}
// Ensure that a valid chain can still pass sync
// Ensure that a valid chain can still pass sync
if
err
:=
tester
.
sync
(
"valid"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"valid"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
}
}
...
@@ -555,11 +565,11 @@ func TestNonExistingBlockAttack60(t *testing.T) {
...
@@ -555,11 +565,11 @@ func TestNonExistingBlockAttack60(t *testing.T) {
tester
.
newPeer
(
"attack"
,
eth60
,
hashes
,
blocks
)
tester
.
newPeer
(
"attack"
,
eth60
,
hashes
,
blocks
)
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
if
err
:=
tester
.
sync
(
"attack"
);
err
!=
errPeersUnavailable
{
if
err
:=
tester
.
sync
(
"attack"
,
nil
);
err
!=
errPeersUnavailable
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errPeersUnavailable
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errPeersUnavailable
)
}
}
// Ensure that a valid chain can still pass sync
// Ensure that a valid chain can still pass sync
if
err
:=
tester
.
sync
(
"valid"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"valid"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
}
}
...
@@ -583,11 +593,11 @@ func TestInvalidHashOrderAttack60(t *testing.T) {
...
@@ -583,11 +593,11 @@ func TestInvalidHashOrderAttack60(t *testing.T) {
tester
.
newPeer
(
"attack"
,
eth60
,
hashes
,
blocks
)
tester
.
newPeer
(
"attack"
,
eth60
,
hashes
,
blocks
)
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
if
err
:=
tester
.
sync
(
"attack"
);
err
!=
errInvalidChain
{
if
err
:=
tester
.
sync
(
"attack"
,
nil
);
err
!=
errInvalidChain
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errInvalidChain
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errInvalidChain
)
}
}
// Ensure that a valid chain can still pass sync
// Ensure that a valid chain can still pass sync
if
err
:=
tester
.
sync
(
"valid"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"valid"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
}
}
...
@@ -611,11 +621,11 @@ func TestMadeupHashChainAttack60(t *testing.T) {
...
@@ -611,11 +621,11 @@ func TestMadeupHashChainAttack60(t *testing.T) {
tester
.
newPeer
(
"attack"
,
eth60
,
randomHashes
,
nil
)
tester
.
newPeer
(
"attack"
,
eth60
,
randomHashes
,
nil
)
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
if
err
:=
tester
.
sync
(
"attack"
);
err
!=
errCrossCheckFailed
{
if
err
:=
tester
.
sync
(
"attack"
,
nil
);
err
!=
errCrossCheckFailed
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
}
}
// Ensure that a valid chain can still pass sync
// Ensure that a valid chain can still pass sync
if
err
:=
tester
.
sync
(
"valid"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"valid"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
}
}
...
@@ -636,7 +646,7 @@ func TestMadeupHashChainDrippingAttack60(t *testing.T) {
...
@@ -636,7 +646,7 @@ func TestMadeupHashChainDrippingAttack60(t *testing.T) {
// Try and sync with the attacker, one hash at a time
// Try and sync with the attacker, one hash at a time
tester
.
maxHashFetch
=
1
tester
.
maxHashFetch
=
1
tester
.
newPeer
(
"attack"
,
eth60
,
randomHashes
,
nil
)
tester
.
newPeer
(
"attack"
,
eth60
,
randomHashes
,
nil
)
if
err
:=
tester
.
sync
(
"attack"
);
err
!=
errStallingPeer
{
if
err
:=
tester
.
sync
(
"attack"
,
nil
);
err
!=
errStallingPeer
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errStallingPeer
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errStallingPeer
)
}
}
}
}
...
@@ -659,7 +669,7 @@ func TestMadeupBlockChainAttack60(t *testing.T) {
...
@@ -659,7 +669,7 @@ func TestMadeupBlockChainAttack60(t *testing.T) {
// Try and sync with the malicious node and check that it fails
// Try and sync with the malicious node and check that it fails
tester
:=
newTester
()
tester
:=
newTester
()
tester
.
newPeer
(
"attack"
,
eth60
,
gapped
,
blocks
)
tester
.
newPeer
(
"attack"
,
eth60
,
gapped
,
blocks
)
if
err
:=
tester
.
sync
(
"attack"
);
err
!=
errCrossCheckFailed
{
if
err
:=
tester
.
sync
(
"attack"
,
nil
);
err
!=
errCrossCheckFailed
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errCrossCheckFailed
)
}
}
// Ensure that a valid chain can still pass sync
// Ensure that a valid chain can still pass sync
...
@@ -667,7 +677,7 @@ func TestMadeupBlockChainAttack60(t *testing.T) {
...
@@ -667,7 +677,7 @@ func TestMadeupBlockChainAttack60(t *testing.T) {
crossCheckCycle
=
defaultCrossCheckCycle
crossCheckCycle
=
defaultCrossCheckCycle
tester
.
newPeer
(
"valid"
,
eth60
,
hashes
,
blocks
)
tester
.
newPeer
(
"valid"
,
eth60
,
hashes
,
blocks
)
if
err
:=
tester
.
sync
(
"valid"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"valid"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
}
}
...
@@ -690,7 +700,7 @@ func TestBannedChainStarvationAttack60(t *testing.T) {
...
@@ -690,7 +700,7 @@ func TestBannedChainStarvationAttack60(t *testing.T) {
// the head of the invalid chain is blocked too.
// the head of the invalid chain is blocked too.
for
banned
:=
tester
.
downloader
.
banned
.
Size
();
;
{
for
banned
:=
tester
.
downloader
.
banned
.
Size
();
;
{
// Try to sync with the attacker, check hash chain failure
// Try to sync with the attacker, check hash chain failure
if
err
:=
tester
.
sync
(
"attack"
);
err
!=
errInvalidChain
{
if
err
:=
tester
.
sync
(
"attack"
,
nil
);
err
!=
errInvalidChain
{
if
tester
.
downloader
.
banned
.
Has
(
forkHashes
[
0
])
&&
err
==
errBannedHead
{
if
tester
.
downloader
.
banned
.
Has
(
forkHashes
[
0
])
&&
err
==
errBannedHead
{
break
break
}
}
...
@@ -711,7 +721,7 @@ func TestBannedChainStarvationAttack60(t *testing.T) {
...
@@ -711,7 +721,7 @@ func TestBannedChainStarvationAttack60(t *testing.T) {
t
.
Fatalf
(
"banned attacker registered: %v"
,
peer
)
t
.
Fatalf
(
"banned attacker registered: %v"
,
peer
)
}
}
// Ensure that a valid chain can still pass sync
// Ensure that a valid chain can still pass sync
if
err
:=
tester
.
sync
(
"valid"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"valid"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
}
}
...
@@ -743,7 +753,7 @@ func TestBannedChainMemoryExhaustionAttack60(t *testing.T) {
...
@@ -743,7 +753,7 @@ func TestBannedChainMemoryExhaustionAttack60(t *testing.T) {
// the head of the invalid chain is blocked too.
// the head of the invalid chain is blocked too.
for
{
for
{
// Try to sync with the attacker, check hash chain failure
// Try to sync with the attacker, check hash chain failure
if
err
:=
tester
.
sync
(
"attack"
);
err
!=
errInvalidChain
{
if
err
:=
tester
.
sync
(
"attack"
,
nil
);
err
!=
errInvalidChain
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errInvalidChain
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errInvalidChain
)
}
}
// Short circuit if the entire chain was banned.
// Short circuit if the entire chain was banned.
...
@@ -754,7 +764,7 @@ func TestBannedChainMemoryExhaustionAttack60(t *testing.T) {
...
@@ -754,7 +764,7 @@ func TestBannedChainMemoryExhaustionAttack60(t *testing.T) {
if
bans
:=
tester
.
downloader
.
banned
.
Size
();
bans
>
maxBannedHashes
{
if
bans
:=
tester
.
downloader
.
banned
.
Size
();
bans
>
maxBannedHashes
{
t
.
Fatalf
(
"ban cap exceeded: have %v, want max %v"
,
bans
,
maxBannedHashes
)
t
.
Fatalf
(
"ban cap exceeded: have %v, want max %v"
,
bans
,
maxBannedHashes
)
}
}
for
hash
,
_
:=
range
core
.
BadHashes
{
for
hash
:=
range
core
.
BadHashes
{
if
!
tester
.
downloader
.
banned
.
Has
(
hash
)
{
if
!
tester
.
downloader
.
banned
.
Has
(
hash
)
{
t
.
Fatalf
(
"hard coded ban evacuated: %x"
,
hash
)
t
.
Fatalf
(
"hard coded ban evacuated: %x"
,
hash
)
}
}
...
@@ -764,7 +774,7 @@ func TestBannedChainMemoryExhaustionAttack60(t *testing.T) {
...
@@ -764,7 +774,7 @@ func TestBannedChainMemoryExhaustionAttack60(t *testing.T) {
MaxBlockFetch
=
defaultMaxBlockFetch
MaxBlockFetch
=
defaultMaxBlockFetch
maxBannedHashes
=
defaultMaxBannedHashes
maxBannedHashes
=
defaultMaxBannedHashes
if
err
:=
tester
.
sync
(
"valid"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"valid"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
}
}
...
@@ -790,7 +800,7 @@ func TestOverlappingDeliveryAttack60(t *testing.T) {
...
@@ -790,7 +800,7 @@ func TestOverlappingDeliveryAttack60(t *testing.T) {
return
rawGetBlocks
(
append
(
request
,
hashes
[
0
]))
return
rawGetBlocks
(
append
(
request
,
hashes
[
0
]))
}
}
// Test that synchronisation can complete, check for import success
// Test that synchronisation can complete, check for import success
if
err
:=
tester
.
sync
(
"attack"
);
err
!=
nil
{
if
err
:=
tester
.
sync
(
"attack"
,
nil
);
err
!=
nil
{
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
t
.
Fatalf
(
"failed to synchronise blocks: %v"
,
err
)
}
}
start
:=
time
.
Now
()
start
:=
time
.
Now
()
...
@@ -807,7 +817,7 @@ func TestOverlappingDeliveryAttack60(t *testing.T) {
...
@@ -807,7 +817,7 @@ func TestOverlappingDeliveryAttack60(t *testing.T) {
func
TestHighTDStarvationAttack61
(
t
*
testing
.
T
)
{
func
TestHighTDStarvationAttack61
(
t
*
testing
.
T
)
{
tester
:=
newTester
()
tester
:=
newTester
()
tester
.
newPeer
(
"attack"
,
eth61
,
[]
common
.
Hash
{
genesis
.
Hash
()},
nil
)
tester
.
newPeer
(
"attack"
,
eth61
,
[]
common
.
Hash
{
genesis
.
Hash
()},
nil
)
if
err
:=
tester
.
sync
(
"attack"
);
err
!=
errStallingPeer
{
if
err
:=
tester
.
sync
(
"attack"
,
big
.
NewInt
(
1000000
)
);
err
!=
errStallingPeer
{
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errStallingPeer
)
t
.
Fatalf
(
"synchronisation error mismatch: have %v, want %v"
,
err
,
errStallingPeer
)
}
}
}
}
...
@@ -849,7 +859,7 @@ func TestHashAttackerDropping(t *testing.T) {
...
@@ -849,7 +859,7 @@ func TestHashAttackerDropping(t *testing.T) {
// Simulate a synchronisation and check the required result
// Simulate a synchronisation and check the required result
tester
.
downloader
.
synchroniseMock
=
func
(
string
,
common
.
Hash
)
error
{
return
tt
.
result
}
tester
.
downloader
.
synchroniseMock
=
func
(
string
,
common
.
Hash
)
error
{
return
tt
.
result
}
tester
.
downloader
.
Synchronise
(
id
,
genesis
.
Hash
())
tester
.
downloader
.
Synchronise
(
id
,
genesis
.
Hash
()
,
big
.
NewInt
(
1000
)
)
if
_
,
ok
:=
tester
.
peerHashes
[
id
];
!
ok
!=
tt
.
drop
{
if
_
,
ok
:=
tester
.
peerHashes
[
id
];
!
ok
!=
tt
.
drop
{
t
.
Errorf
(
"test %d: peer drop mismatch for %v: have %v, want %v"
,
i
,
tt
.
result
,
!
ok
,
tt
.
drop
)
t
.
Errorf
(
"test %d: peer drop mismatch for %v: have %v, want %v"
,
i
,
tt
.
result
,
!
ok
,
tt
.
drop
)
}
}
...
...
eth/sync.go
View file @
6adbaabc
...
@@ -164,5 +164,5 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
...
@@ -164,5 +164,5 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
return
return
}
}
// Otherwise try to sync with the downloader
// Otherwise try to sync with the downloader
pm
.
downloader
.
Synchronise
(
peer
.
id
,
peer
.
Head
())
pm
.
downloader
.
Synchronise
(
peer
.
id
,
peer
.
Head
()
,
peer
.
Td
()
)
}
}
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