diff --git a/src/com/google/bitcoin/core/NetworkConnection.java b/src/com/google/bitcoin/core/NetworkConnection.java index eea12c55..b6c9c437 100644 --- a/src/com/google/bitcoin/core/NetworkConnection.java +++ b/src/com/google/bitcoin/core/NetworkConnection.java @@ -61,12 +61,15 @@ public class NetworkConnection { /** * Connect to the given IP address using the port specified as part of the network parameters. Once construction * is complete a functioning network channel is set up and running. + * * @param remoteIp IP address to connect to. IPv6 is not currently supported by BitCoin. * @param params Defines which network to connect to and details of the protocol. + * @param bestHeight How many blocks are in our best chain * @throws IOException if there is a network related failure. * @throws ProtocolException if the version negotiation failed. */ - public NetworkConnection(InetAddress remoteIp, NetworkParameters params) throws IOException, ProtocolException { + public NetworkConnection(InetAddress remoteIp, NetworkParameters params, int bestHeight) + throws IOException, ProtocolException { this.params = params; this.remoteIp = remoteIp; socket = new Socket(remoteIp, params.port); @@ -75,7 +78,7 @@ public class NetworkConnection { // Announce ourselves. This has to come first to connect to clients beyond v0.30.20.2 which wait to hear // from us until they send their version message back. - writeMessage(MSG_VERSION, new VersionMessage(params)); + writeMessage(MSG_VERSION, new VersionMessage(params, bestHeight)); // When connecting, the remote peer sends us a version message with various bits of // useful data in it. We need to know the peer protocol version before we can talk to it. versionMessage = (VersionMessage) readMessage(); diff --git a/src/com/google/bitcoin/core/PeerAddress.java b/src/com/google/bitcoin/core/PeerAddress.java index c3b417f7..f5c627a8 100644 --- a/src/com/google/bitcoin/core/PeerAddress.java +++ b/src/com/google/bitcoin/core/PeerAddress.java @@ -42,15 +42,18 @@ public class PeerAddress extends Message { super(params, payload, offset, protocolVersion); } - public PeerAddress(InetAddress addr, int port) { + public PeerAddress(InetAddress addr, int port, int protocolVersion) { this.addr = addr; this.port = port; + this.protocolVersion = protocolVersion; } public void bitcoinSerializeToStream(OutputStream stream) throws IOException { - int secs = (int)(new Date().getTime() / 1000); - uint32ToByteStreamLE(secs, stream); - uint64ToByteStreamLE(BigInteger.ZERO, stream); + if (protocolVersion >= 31402) { + int secs = (int)(new Date().getTime() / 1000); + uint32ToByteStreamLE(secs, stream); + } + uint64ToByteStreamLE(BigInteger.ZERO, stream); // nServices. // Java does not provide any utility to map an IPv4 address into IPv6 space, so we have to do it by hand. byte[] ipBytes = addr.getAddress(); if (ipBytes.length == 4) { diff --git a/src/com/google/bitcoin/core/VersionMessage.java b/src/com/google/bitcoin/core/VersionMessage.java index d273cfce..5d78c104 100644 --- a/src/com/google/bitcoin/core/VersionMessage.java +++ b/src/com/google/bitcoin/core/VersionMessage.java @@ -18,7 +18,6 @@ package com.google.bitcoin.core; import java.io.IOException; import java.io.OutputStream; -import java.math.BigInteger; import java.net.InetAddress; import java.net.UnknownHostException; @@ -52,7 +51,7 @@ public class VersionMessage extends Message { super(params, msg, 0); } - public VersionMessage(NetworkParameters params) { + public VersionMessage(NetworkParameters params, int newBestHeight) { super(params); clientVersion = NetworkParameters.PROTOCOL_VERSION; localServices = 0; @@ -60,13 +59,13 @@ public class VersionMessage extends Message { // Note that the official client 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. try { - myAddr = new PeerAddress(InetAddress.getLocalHost(), params.port); - theirAddr = new PeerAddress(InetAddress.getLocalHost(), params.port); + myAddr = new PeerAddress(InetAddress.getLocalHost(), params.port, 0); + theirAddr = new PeerAddress(InetAddress.getLocalHost(), params.port, 0); } catch (UnknownHostException e) { throw new RuntimeException(e); // Cannot happen. } - subVer = "BitCoinJ 0.1.99"; - bestHeight = 0; + subVer = "BitCoinJ 0.2"; + bestHeight = newBestHeight; } @Override @@ -92,8 +91,9 @@ public class VersionMessage extends Message { public void bitcoinSerializeToStream(OutputStream buf) throws IOException { Utils.uint32ToByteStreamLE(clientVersion, buf); Utils.uint32ToByteStreamLE(localServices, buf); - Utils.uint32ToByteStreamLE(time >> 32, buf); + Utils.uint32ToByteStreamLE(localServices >> 32, buf); Utils.uint32ToByteStreamLE(time, buf); + Utils.uint32ToByteStreamLE(time >> 32, buf); try { // My address. myAddr.bitcoinSerializeToStream(buf); diff --git a/src/com/google/bitcoin/examples/PingService.java b/src/com/google/bitcoin/examples/PingService.java index a32bc1b2..21ee2644 100644 --- a/src/com/google/bitcoin/examples/PingService.java +++ b/src/com/google/bitcoin/examples/PingService.java @@ -31,11 +31,13 @@ import java.util.concurrent.TimeUnit; */ public class PingService { public static void main(String[] args) throws Exception { - final NetworkParameters params = NetworkParameters.prodNet(); + boolean testNet = args.length > 0 && args[0].equalsIgnoreCase("testnet"); + final NetworkParameters params = testNet ? NetworkParameters.testNet() : NetworkParameters.prodNet(); + String filePrefix = testNet ? "pingservice-testnet" : "pingservice-prodnet"; // Try to read the wallet from storage, create a new one if not possible. Wallet wallet; - final File walletFile = new File("pingservice.wallet"); + final File walletFile = new File(filePrefix + ".wallet"); try { wallet = Wallet.loadFromFile(walletFile); } catch (IOException e) { @@ -48,11 +50,12 @@ public class PingService { // Load the block chain, if there is one stored locally. System.out.println("Reading block store from disk"); - BlockStore blockStore = new DiskBlockStore(params, new File("pingservice.blockchain")); + BlockStore blockStore = new DiskBlockStore(params, new File(filePrefix + ".blockchain")); // Connect to the localhost node. System.out.println("Connecting ..."); - NetworkConnection conn = new NetworkConnection(InetAddress.getLocalHost(), params); + NetworkConnection conn = new NetworkConnection(InetAddress.getLocalHost(), params, + blockStore.getChainHead().getHeight()); BlockChain chain = new BlockChain(params, wallet, blockStore); final Peer peer = new Peer(params, conn, chain); peer.start(); @@ -61,7 +64,7 @@ public class PingService { wallet.addEventListener(new WalletEventListener() { public void onCoinsReceived(Wallet w, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { // Running on a peer thread. - + assert !newBalance.equals(BigInteger.ZERO); // It's impossible to pick one specific identity that you receive coins from in BitCoin as there // could be inputs from many addresses. So instead we just pick the first and assume they were all // owned by the same person. diff --git a/src/com/google/bitcoin/examples/PrivateKeys.java b/src/com/google/bitcoin/examples/PrivateKeys.java index 69652cf9..cd5f61b4 100644 --- a/src/com/google/bitcoin/examples/PrivateKeys.java +++ b/src/com/google/bitcoin/examples/PrivateKeys.java @@ -46,7 +46,7 @@ public class PrivateKeys { wallet.addKey(key); // Find the transactions that involve those coins. - NetworkConnection conn = new NetworkConnection(InetAddress.getLocalHost(), params); + NetworkConnection conn = new NetworkConnection(InetAddress.getLocalHost(), params, 0); BlockChain chain = new BlockChain(params, wallet, new MemoryBlockStore(params)); Peer peer = new Peer(params, conn, chain); peer.start();