diff --git a/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java b/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java index 274394df1..2be791976 100644 --- a/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java +++ b/core/src/main/java/org/bitcoinj/core/BitcoinSerializer.java @@ -217,7 +217,7 @@ public class BitcoinSerializer extends MessageSerializer { ByteBuffer payload = ByteBuffer.wrap(payloadBytes); // We use an if ladder rather than reflection because reflection is very slow on Android. if (command.equals("version")) { - return new VersionMessage(params, payload); + return new VersionMessage(payload); } else if (command.equals("inv")) { return makeInventoryMessage(payload); } else if (command.equals("block")) { diff --git a/core/src/main/java/org/bitcoinj/core/VersionMessage.java b/core/src/main/java/org/bitcoinj/core/VersionMessage.java index 1ac014364..2a8060f52 100644 --- a/core/src/main/java/org/bitcoinj/core/VersionMessage.java +++ b/core/src/main/java/org/bitcoinj/core/VersionMessage.java @@ -89,28 +89,41 @@ public class VersionMessage extends Message { */ public boolean relayTxesBeforeFilter; - public VersionMessage(NetworkParameters params, ByteBuffer payload) throws ProtocolException { - super(params, payload); + public VersionMessage(ByteBuffer payload) throws ProtocolException { + super(payload); } - // It doesn't really make sense to ever lazily parse a version message or to retain the backing bytes. - // If you're receiving this on the wire you need to check the protocol version and it will never need to be sent - // back down the wire. - - public VersionMessage(NetworkParameters params, int newBestHeight) { - super(params); - clientVersion = serializer.getProtocolVersion(); - localServices = Services.none(); - time = TimeUtils.currentTime().truncatedTo(ChronoUnit.SECONDS); + /** + * Construct own version message from given {@link NetworkParameters} and our best height of the chain. + * + * @param params network parameters to construct own version message from + * @param bestHeight our best height to announce + */ + public VersionMessage(NetworkParameters params, int bestHeight) { + this.clientVersion = params.getProtocolVersionNum(NetworkParameters.ProtocolVersion.CURRENT); + this.localServices = Services.none(); + this.time = TimeUtils.currentTime().truncatedTo(ChronoUnit.SECONDS); // Note that the Bitcoin Core doesn't do anything with these, and finding out your own external IP address // is kind of tricky anyway, so we just put nonsense here for now. InetAddress localhost = InetAddresses.forString("127.0.0.1"); MessageSerializer serializer = new DummySerializer(0); - receivingAddr = new PeerAddress(localhost, params.getPort(), Services.none(), serializer); - fromAddr = new PeerAddress(localhost, params.getPort(), Services.none(), serializer); - subVer = LIBRARY_SUBVER; - bestHeight = newBestHeight; - relayTxesBeforeFilter = true; + this.receivingAddr = new PeerAddress(localhost, params.getPort(), Services.none(), serializer); + this.fromAddr = new PeerAddress(localhost, params.getPort(), Services.none(), serializer); + this.subVer = LIBRARY_SUBVER; + this.bestHeight = bestHeight; + this.relayTxesBeforeFilter = true; + } + + private VersionMessage(int clientVersion, Services localServices, Instant time, PeerAddress receivingAddr, + PeerAddress fromAddr, String subVer, long bestHeight, boolean relayTxesBeforeFilter) { + this.clientVersion = clientVersion; + this.localServices = localServices; + this.time = time; + this.receivingAddr = receivingAddr; + this.fromAddr = fromAddr; + this.subVer = subVer; + this.bestHeight = bestHeight; + this.relayTxesBeforeFilter = relayTxesBeforeFilter; } /** @@ -214,15 +227,8 @@ public class VersionMessage extends Message { } public VersionMessage duplicate() { - VersionMessage v = new VersionMessage(params, (int) bestHeight); - v.clientVersion = clientVersion; - v.localServices = localServices; - v.time = time; - v.receivingAddr = receivingAddr; - v.fromAddr = fromAddr; - v.subVer = subVer; - v.relayTxesBeforeFilter = relayTxesBeforeFilter; - return v; + return new VersionMessage(clientVersion, localServices, time, receivingAddr, fromAddr, subVer, bestHeight, + relayTxesBeforeFilter); } /** diff --git a/core/src/test/java/org/bitcoinj/core/VersionMessageTest.java b/core/src/test/java/org/bitcoinj/core/VersionMessageTest.java index eec050a88..0cc0ce310 100644 --- a/core/src/test/java/org/bitcoinj/core/VersionMessageTest.java +++ b/core/src/test/java/org/bitcoinj/core/VersionMessageTest.java @@ -36,7 +36,7 @@ public class VersionMessageTest { public void decode_noRelay_bestHeight_subVer() { // Test that we can decode version messages which miss data which some old nodes may not include String hex = "7111010000000000000000003334a85500000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d00000000000000000f2f626974636f696e6a3a302e31332f0004000000"; - VersionMessage ver = new VersionMessage(TESTNET, ByteBuffer.wrap(ByteUtils.parseHex(hex))); + VersionMessage ver = new VersionMessage(ByteBuffer.wrap(ByteUtils.parseHex(hex))); assertFalse(ver.relayTxesBeforeFilter); assertEquals(1024, ver.bestHeight); assertEquals("/bitcoinj:0.13/", ver.subVer); @@ -45,7 +45,7 @@ public class VersionMessageTest { @Test public void decode_relay_bestHeight_subVer() { String hex = "711101000000000000000000a634a85500000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d00000000000000000f2f626974636f696e6a3a302e31332f0004000001"; - VersionMessage ver = new VersionMessage(TESTNET, ByteBuffer.wrap(ByteUtils.parseHex(hex))); + VersionMessage ver = new VersionMessage(ByteBuffer.wrap(ByteUtils.parseHex(hex))); assertTrue(ver.relayTxesBeforeFilter); assertEquals(1024, ver.bestHeight); assertEquals("/bitcoinj:0.13/", ver.subVer); @@ -54,7 +54,7 @@ public class VersionMessageTest { @Test public void decode_relay_noBestHeight_subVer() { String hex = "711101000000000000000000c334a85500000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d00000000000000000f2f626974636f696e6a3a302e31332f0000000001"; - VersionMessage ver = new VersionMessage(TESTNET, ByteBuffer.wrap(ByteUtils.parseHex(hex))); + VersionMessage ver = new VersionMessage(ByteBuffer.wrap(ByteUtils.parseHex(hex))); assertTrue(ver.relayTxesBeforeFilter); assertEquals(0, ver.bestHeight); assertEquals("/bitcoinj:0.13/", ver.subVer); @@ -63,7 +63,7 @@ public class VersionMessageTest { @Test(expected = ProtocolException.class) public void decode_relay_noBestHeight_noSubVer() { String hex = "00000000000000000000000048e5e95000000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d0000000000000000"; - VersionMessage ver = new VersionMessage(TESTNET, ByteBuffer.wrap(ByteUtils.parseHex(hex))); + VersionMessage ver = new VersionMessage(ByteBuffer.wrap(ByteUtils.parseHex(hex))); } @Test @@ -71,12 +71,11 @@ public class VersionMessageTest { VersionMessage ver = new VersionMessage(TESTNET, 1234); ver.time = Instant.ofEpochSecond(23456); ver.subVer = "/bitcoinj/"; - ver.clientVersion = NetworkParameters.ProtocolVersion.CURRENT.getBitcoinProtocolVersion(); ver.localServices = Services.of(1); ver.fromAddr = new PeerAddress(InetAddress.getByName("1.2.3.4"), 3888); ver.receivingAddr = new PeerAddress(InetAddress.getByName("4.3.2.1"), 8333); byte[] serialized = ver.bitcoinSerialize(); - VersionMessage ver2 = new VersionMessage(TESTNET, ByteBuffer.wrap(serialized)); + VersionMessage ver2 = new VersionMessage(ByteBuffer.wrap(serialized)); assertEquals(1234, ver2.bestHeight); assertEquals(Instant.ofEpochSecond(23456), ver2.time); assertEquals("/bitcoinj/", ver2.subVer); @@ -93,12 +92,11 @@ public class VersionMessageTest { VersionMessage ver = new VersionMessage(TESTNET, 1234); ver.time = Instant.ofEpochSecond(23456); ver.subVer = "/bitcoinj/"; - ver.clientVersion = NetworkParameters.ProtocolVersion.CURRENT.getBitcoinProtocolVersion(); ver.localServices = Services.of(1); ver.fromAddr = new PeerAddress(InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7334"), 3888); ver.receivingAddr = new PeerAddress(InetAddress.getByName("2002:db8:85a3:0:0:8a2e:370:7335"), 8333); byte[] serialized = ver.bitcoinSerialize(); - VersionMessage ver2 = new VersionMessage(TESTNET, ByteBuffer.wrap(serialized)); + VersionMessage ver2 = new VersionMessage(ByteBuffer.wrap(serialized)); assertEquals(1234, ver2.bestHeight); assertEquals(Instant.ofEpochSecond(23456), ver2.time); assertEquals("/bitcoinj/", ver2.subVer);