eth/downloader: accumulating hash bans for reconnecting attackers
This commit is contained in:
@ -14,6 +14,7 @@ import (
|
||||
var (
|
||||
knownHash = common.Hash{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
|
||||
unknownHash = common.Hash{9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9}
|
||||
bannedHash = common.Hash{5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}
|
||||
)
|
||||
|
||||
func createHashes(start, amount int) (hashes []common.Hash) {
|
||||
@ -520,3 +521,37 @@ func TestMadeupParentBlockChainAttack(t *testing.T) {
|
||||
t.Fatalf("failed to synchronise blocks: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Tests that if one/multiple malicious peers try to feed a banned blockchain to
|
||||
// the downloader, it will not keep refetching the same chain indefinitely, but
|
||||
// gradually block pieces of it, until it's head is also blocked.
|
||||
func TestBannedChainStarvationAttack(t *testing.T) {
|
||||
// Construct a valid chain, but ban one of the hashes in it
|
||||
hashes := createHashes(0, 8*blockCacheLimit)
|
||||
hashes[len(hashes)/2+23] = bannedHash // weird index to have non multiple of ban chunk size
|
||||
|
||||
blocks := createBlocksFromHashes(hashes)
|
||||
|
||||
// Create the tester and ban the selected hash
|
||||
tester := newTester(t, hashes, blocks)
|
||||
tester.downloader.banned.Add(bannedHash)
|
||||
|
||||
// Iteratively try to sync, and verify that the banned hash list grows until
|
||||
// the head of the invalid chain is blocked too.
|
||||
tester.newPeer("attack", big.NewInt(10000), hashes[0])
|
||||
for banned := tester.downloader.banned.Size(); ; {
|
||||
// Try to sync with the attacker, check hash chain failure
|
||||
if _, err := tester.syncTake("attack", hashes[0]); err != ErrInvalidChain {
|
||||
t.Fatalf("synchronisation error mismatch: have %v, want %v", err, ErrInvalidChain)
|
||||
}
|
||||
// Check that the ban list grew with at least 1 new item, or all banned
|
||||
bans := tester.downloader.banned.Size()
|
||||
if bans < banned+1 {
|
||||
if tester.downloader.banned.Has(hashes[0]) {
|
||||
break
|
||||
}
|
||||
t.Fatalf("ban count mismatch: have %v, want %v+", bans, banned+1)
|
||||
}
|
||||
banned = bans
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user