aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeffrey Wilcke <jeffrey@ethereum.org>2015-06-17 18:24:46 +0800
committerJeffrey Wilcke <jeffrey@ethereum.org>2015-06-17 18:24:46 +0800
commite4b54f18c6db9f43a4d6cf2916df664bf30c8171 (patch)
tree04f59a1fb8e7093607393f536e81b5078ac38b82
parenta3fdef7529e9b58b73d5eb033a2411fafbc9a1f1 (diff)
parent4a1e82cf3f7a5c9d7526fc01aa68466870e2a644 (diff)
downloaddexon-e4b54f18c6db9f43a4d6cf2916df664bf30c8171.tar
dexon-e4b54f18c6db9f43a4d6cf2916df664bf30c8171.tar.gz
dexon-e4b54f18c6db9f43a4d6cf2916df664bf30c8171.tar.bz2
dexon-e4b54f18c6db9f43a4d6cf2916df664bf30c8171.tar.lz
dexon-e4b54f18c6db9f43a4d6cf2916df664bf30c8171.tar.xz
dexon-e4b54f18c6db9f43a4d6cf2916df664bf30c8171.tar.zst
dexon-e4b54f18c6db9f43a4d6cf2916df664bf30c8171.zip
Merge pull request #1281 from karalabe/fix-overlapping-delivery-hang
eth/downloader: fix #1280, overlapping (good/bad) delivery hang
-rw-r--r--eth/downloader/downloader.go1
-rw-r--r--eth/downloader/downloader_test.go34
2 files changed, 35 insertions, 0 deletions
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index 306c4fd2d..c7a05eb35 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -548,6 +548,7 @@ out:
peer.Demote()
peer.SetIdle()
glog.V(logger.Detail).Infof("%s: delivery partially failed: %v", peer, err)
+ go d.process()
}
}
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index f71c16237..53eb5f81d 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -708,6 +708,40 @@ func TestBannedChainMemoryExhaustionAttack(t *testing.T) {
}
}
+// Tests a corner case (potential attack) where a peer delivers both good as well
+// as unrequested blocks to a hash request. This may trigger a different code
+// path than the fully correct or fully invalid delivery, potentially causing
+// internal state problems
+//
+// No, don't delete this test, it actually did happen!
+func TestOverlappingDeliveryAttack(t *testing.T) {
+ // Create an arbitrary batch of blocks ( < cache-size not to block)
+ targetBlocks := blockCacheLimit - 23
+ hashes := createHashes(targetBlocks, knownHash)
+ blocks := createBlocksFromHashes(hashes)
+
+ // Register an attacker that always returns non-requested blocks too
+ tester := newTester()
+ tester.newPeer("attack", hashes, blocks)
+
+ rawGetBlocks := tester.downloader.peers.Peer("attack").getBlocks
+ tester.downloader.peers.Peer("attack").getBlocks = func(request []common.Hash) error {
+ // Add a non requested hash the screw the delivery (genesis should be fine)
+ return rawGetBlocks(append(request, hashes[0]))
+ }
+ // Test that synchronisation can complete, check for import success
+ if err := tester.sync("attack"); err != nil {
+ t.Fatalf("failed to synchronise blocks: %v", err)
+ }
+ start := time.Now()
+ for len(tester.ownHashes) != len(hashes) && time.Since(start) < time.Second {
+ time.Sleep(50 * time.Millisecond)
+ }
+ if len(tester.ownHashes) != len(hashes) {
+ t.Fatalf("chain length mismatch: have %v, want %v", len(tester.ownHashes), len(hashes))
+ }
+}
+
// Tests that misbehaving peers are disconnected, whilst behaving ones are not.
func TestHashAttackerDropping(t *testing.T) {
// Define the disconnection requirement for individual hash fetch errors