diff options
author | Péter Szilágyi <peterke@gmail.com> | 2015-06-08 19:06:36 +0800 |
---|---|---|
committer | Péter Szilágyi <peterke@gmail.com> | 2015-06-08 19:12:00 +0800 |
commit | 63c6cedb14cbd461733e33ffac016dc7d8e431ae (patch) | |
tree | a1593178989ed92561b37dceb90fbf7401af4b10 /eth/downloader/downloader_test.go | |
parent | 4b2dd44711a04c639ecde68806455ccf7244acce (diff) | |
download | dexon-63c6cedb14cbd461733e33ffac016dc7d8e431ae.tar.gz dexon-63c6cedb14cbd461733e33ffac016dc7d8e431ae.tar.zst dexon-63c6cedb14cbd461733e33ffac016dc7d8e431ae.zip |
eth/downloader: cap the hash ban set, add test for it
Diffstat (limited to 'eth/downloader/downloader_test.go')
-rw-r--r-- | eth/downloader/downloader_test.go | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 4219c2788..c9e84371c 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -7,6 +7,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/event" ) @@ -559,3 +560,45 @@ func TestBannedChainStarvationAttack(t *testing.T) { banned = bans } } + +// Tests that if a peer sends excessively many/large invalid chains that are +// gradually banned, it will have an upper limit on the consumed memory and also +// the origin bad hashes will not be evacuated. +func TestBannedChainMemoryExhaustionAttack(t *testing.T) { + // Reduce the test size a bit + MaxBlockFetch = 4 + maxBannedHashes = 256 + + // Construct a banned chain with more chunks than the ban limit + hashes := createHashes(0, maxBannedHashes*MaxBlockFetch) + hashes[len(hashes)-1] = 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 { + // 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) + } + // Short circuit if the entire chain was banned + if tester.downloader.banned.Has(hashes[0]) { + break + } + // Otherwise ensure we never exceed the memory allowance and the hard coded bans are untouched + if bans := tester.downloader.banned.Size(); bans > maxBannedHashes { + t.Fatalf("ban cap exceeded: have %v, want max %v", bans, maxBannedHashes) + } + for hash, _ := range core.BadHashes { + if !tester.downloader.banned.Has(hash) { + t.Fatalf("hard coded ban evacuated: %x", hash) + } + } + } +} |