diff --git a/core/src/main/java/com/google/bitcoin/core/Peer.java b/core/src/main/java/com/google/bitcoin/core/Peer.java index ad20a988..29ec8379 100644 --- a/core/src/main/java/com/google/bitcoin/core/Peer.java +++ b/core/src/main/java/com/google/bitcoin/core/Peer.java @@ -237,7 +237,9 @@ public class Peer { } else if (m instanceof AlertMessage) { processAlert((AlertMessage)m); } else if (m instanceof VersionMessage) { - peerVersionMessage = (VersionMessage)m; + synchronized (Peer.this) { + peerVersionMessage = (VersionMessage)m; + } EventListenerInvoker.invoke(lifecycleListeners, new EventListenerInvoker() { @Override public void invoke(PeerLifecycleListener listener) { @@ -245,13 +247,15 @@ public class Peer { } }); } else if (m instanceof VersionAck) { - if (peerVersionMessage == null) { - throw new ProtocolException("got a version ack before version"); + synchronized (Peer.this) { + if (peerVersionMessage == null) { + throw new ProtocolException("got a version ack before version"); + } + if (isAcked) { + throw new ProtocolException("got more than one version ack"); + } + isAcked = true; } - if (isAcked) { - throw new ProtocolException("got more than one version ack"); - } - isAcked = true; } else if (m instanceof Ping) { if (((Ping) m).hasNonce()) sendMessage(new Pong(((Ping) m).getNonce())); @@ -424,7 +428,7 @@ public class Peer { // It is possible for the peer block height difference to be negative when blocks have been solved and broadcast // since the time we first connected to the peer. However, it's weird and unexpected to receive a callback // with negative "blocks left" in this case, so we clamp to zero so the API user doesn't have to think about it. - final int blocksLeft = Math.max(0, getPeerBlockHeightDifference()); + final int blocksLeft = Math.max(0, (int)peerVersionMessage.bestHeight - blockChain.getBestChainHeight()); EventListenerInvoker.invoke(eventListeners, new EventListenerInvoker() { @Override public void invoke(PeerEventListener listener) { @@ -868,7 +872,7 @@ public class Peer { // client-mode node, nor should it be unconnected. If that happens it means the user overrode us somewhere or // there is a bug in the peer management code. Preconditions.checkState(params.allowEmptyPeerChains || chainHeight > 0, "Connected to peer with zero/negative chain height", chainHeight); - return chainHeight - blockChain.getChainHead().getHeight(); + return chainHeight - blockChain.getBestChainHeight(); } /** diff --git a/core/src/test/java/com/google/bitcoin/core/PeerTest.java b/core/src/test/java/com/google/bitcoin/core/PeerTest.java index f5394442..7f3185bf 100644 --- a/core/src/test/java/com/google/bitcoin/core/PeerTest.java +++ b/core/src/test/java/com/google/bitcoin/core/PeerTest.java @@ -310,10 +310,8 @@ public class PeerTest extends TestWithNetworkConnections { inv.addItem(item); expect(listener.onPreMessageReceived(eq(peer), eq(inv))).andReturn(inv); expect(listener.onPreMessageReceived(eq(peer), eq(b2))).andReturn(b2); - // We have two blocks in our chain (genesis and b1), so our height is 2. The other peer starts at - // OTHER_PEER_CHAIN_HEIGHT and then when it announces an inv, its height is + 1, so the difference - // between our height and theirs is OTHER_PEER_CHAIN_HEIGHT + 1 - 2. - listener.onBlocksDownloaded(eq(peer), anyObject(Block.class), eq(OTHER_PEER_CHAIN_HEIGHT + 1 - 2)); + // The listener gets the delta between the first announced height and our height. + listener.onBlocksDownloaded(eq(peer), anyObject(Block.class), eq(OTHER_PEER_CHAIN_HEIGHT - 2)); expectLastCall(); control.replay();