eth/downloader: check sync after failed attacks

This commit is contained in:
Péter Szilágyi 2015-05-15 02:14:21 +03:00
parent 366e9627e8
commit bcc2980179
2 changed files with 23 additions and 7 deletions

View File

@ -268,8 +268,12 @@ out:
// Insert all the new hashes, but only continue if got something useful // Insert all the new hashes, but only continue if got something useful
inserts := d.queue.Insert(hashPack.hashes) inserts := d.queue.Insert(hashPack.hashes)
if inserts == 0 && !done { if inserts == 0 && !done {
glog.V(logger.Debug).Infof("Peer (%s) responded with stale hashes\n", activePeer.id)
d.queue.Reset()
return ErrBadPeer return ErrBadPeer
} else if !done { }
if !done {
activePeer.getHashes(hash) activePeer.getHashes(hash)
continue continue
} }

View File

@ -342,14 +342,13 @@ func TestNonExistingParentAttack(t *testing.T) {
// loop indefinitely. // loop indefinitely.
func TestRepeatingHashAttack(t *testing.T) { func TestRepeatingHashAttack(t *testing.T) {
// Create a valid chain, but drop the last link // Create a valid chain, but drop the last link
hashes := createHashes(0, 1000) hashes := createHashes(0, blockCacheLimit)
blocks := createBlocksFromHashes(hashes) blocks := createBlocksFromHashes(hashes)
forged := hashes[:len(hashes)-1]
hashes = hashes[:len(hashes)-1]
// Try and sync with the malicious node // Try and sync with the malicious node
tester := newTester(t, hashes, blocks) tester := newTester(t, forged, blocks)
tester.newPeer("attack", big.NewInt(10000), hashes[0]) tester.newPeer("attack", big.NewInt(10000), forged[0])
errc := make(chan error) errc := make(chan error)
go func() { go func() {
@ -365,14 +364,21 @@ func TestRepeatingHashAttack(t *testing.T) {
t.Fatalf("synchronisation succeeded") t.Fatalf("synchronisation succeeded")
} }
} }
// Ensure that a valid chain can still pass sync
tester.hashes = hashes
tester.newPeer("valid", big.NewInt(20000), hashes[0])
if err := tester.sync("valid", hashes[0]); err != nil {
t.Fatalf("failed to synchronise blocks: %v", err)
}
} }
// Tests that if a malicious peers returns a non-existent block hash, it should // Tests that if a malicious peers returns a non-existent block hash, it should
// eventually time out and the sync reattempted. // eventually time out and the sync reattempted.
func TestNonExistingBlockAttack(t *testing.T) { func TestNonExistingBlockAttack(t *testing.T) {
// Create a valid chain, but forge the last link // Create a valid chain, but forge the last link
hashes := createHashes(0, 10) hashes := createHashes(0, blockCacheLimit)
blocks := createBlocksFromHashes(hashes) blocks := createBlocksFromHashes(hashes)
origin := hashes[len(hashes)/2]
hashes[len(hashes)/2] = unknownHash hashes[len(hashes)/2] = unknownHash
@ -382,4 +388,10 @@ func TestNonExistingBlockAttack(t *testing.T) {
if err := tester.sync("attack", hashes[0]); err != errPeersUnavailable { if err := tester.sync("attack", hashes[0]); 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
hashes[len(hashes)/2] = origin
tester.newPeer("valid", big.NewInt(20000), hashes[0])
if err := tester.sync("valid", hashes[0]); err != nil {
t.Fatalf("failed to synchronise blocks: %v", err)
}
} }