From d2e4284930e00b9685b8832815199f3312c3b200 Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Fri, 21 Oct 2011 09:57:59 +0000 Subject: [PATCH] Improve the block locator we send to remote peers as a temporary hack for the lack of exponential thinning. Patch from Jan. Updates issue 84. --- src/com/google/bitcoin/core/Peer.java | 19 ++++++++++++++++--- tests/com/google/bitcoin/core/PeerTest.java | 3 +++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/com/google/bitcoin/core/Peer.java b/src/com/google/bitcoin/core/Peer.java index a40c85f9..2597b021 100644 --- a/src/com/google/bitcoin/core/Peer.java +++ b/src/com/google/bitcoin/core/Peer.java @@ -358,12 +358,25 @@ public class Peer { // TODO: Block locators should be abstracted out rather than special cased here. List blockLocator = new LinkedList(); - // We don't do the exponential thinning here, so if we get onto a fork of the chain we will end up - // redownloading the whole thing again. + // For now we don't do the exponential thinning as suggested here: + // https://en.bitcoin.it/wiki/Protocol_specification#getblocks + // However, this should be taken seriously going forward. The old implementation only added the hash of the + // genesis block and the current chain head, which randomly led us to halt block fetching when ending on a + // chain that turned out not to be the longest. This happened roughly once a week. + // Now we add three hashes to the locator: + // 1. Hash of genesis block + // 2. Hash of the block previous to the chain head + // 3. Hash of the chain head + // This allows our peer to see that we are on the wrong track if we ended up on the wrong side of a chain fork + // if the fork is only one block deep. blockLocator.add(params.genesisBlock.getHash()); Block topBlock = blockChain.getChainHead().getHeader(); - if (!topBlock.equals(params.genesisBlock)) + if (!topBlock.equals(params.genesisBlock)) { + if (!topBlock.getPrevBlockHash().equals(params.genesisBlock)){ + blockLocator.add(0, topBlock.getPrevBlockHash()); + } blockLocator.add(0, topBlock.getHash()); + } GetBlocksMessage message = new GetBlocksMessage(params, blockLocator, toHash); conn.writeMessage(message); } diff --git a/tests/com/google/bitcoin/core/PeerTest.java b/tests/com/google/bitcoin/core/PeerTest.java index 062270cc..ffcbca22 100644 --- a/tests/com/google/bitcoin/core/PeerTest.java +++ b/tests/com/google/bitcoin/core/PeerTest.java @@ -136,6 +136,7 @@ public class PeerTest { List expectedLocator = new ArrayList(); expectedLocator.add(b1.getHash()); + expectedLocator.add(b1.getPrevBlockHash()); expectedLocator.add(unitTestParams.genesisBlock.getHash()); assertEquals(message.getValue().getLocator(), expectedLocator); @@ -171,6 +172,7 @@ public class PeerTest { List expectedLocator = new ArrayList(); expectedLocator.add(b1.getHash()); + expectedLocator.add(b1.getPrevBlockHash()); expectedLocator.add(unitTestParams.genesisBlock.getHash()); assertEquals(message.getValue().getLocator(), expectedLocator); @@ -234,6 +236,7 @@ public class PeerTest { List expectedLocator = new ArrayList(); expectedLocator.add(b1.getHash()); + expectedLocator.add(b1.getPrevBlockHash()); expectedLocator.add(unitTestParams.genesisBlock.getHash()); assertEquals(message.getValue().getLocator(), expectedLocator);