3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-07 14:54:15 +00:00

Some small protocol fixes. Correct serialization of version and address messages.

Also require the height of the best chain to be specified when setting up a NetworkConnection. This API is getting too complicated and will be simplified soon. 

For now these fixes resolve a bug whereby the peer would not send us new blocks discovered during a session (as it thought we already had them).
This commit is contained in:
Mike Hearn 2011-04-25 21:52:33 +00:00
parent 84dcfecb5d
commit 86d7b15f8c
5 changed files with 28 additions and 19 deletions

View File

@ -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 * 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. * 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 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 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 IOException if there is a network related failure.
* @throws ProtocolException if the version negotiation failed. * @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.params = params;
this.remoteIp = remoteIp; this.remoteIp = remoteIp;
socket = new Socket(remoteIp, params.port); 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 // 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. // 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 // 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. // useful data in it. We need to know the peer protocol version before we can talk to it.
versionMessage = (VersionMessage) readMessage(); versionMessage = (VersionMessage) readMessage();

View File

@ -42,15 +42,18 @@ public class PeerAddress extends Message {
super(params, payload, offset, protocolVersion); super(params, payload, offset, protocolVersion);
} }
public PeerAddress(InetAddress addr, int port) { public PeerAddress(InetAddress addr, int port, int protocolVersion) {
this.addr = addr; this.addr = addr;
this.port = port; this.port = port;
this.protocolVersion = protocolVersion;
} }
public void bitcoinSerializeToStream(OutputStream stream) throws IOException { public void bitcoinSerializeToStream(OutputStream stream) throws IOException {
if (protocolVersion >= 31402) {
int secs = (int)(new Date().getTime() / 1000); int secs = (int)(new Date().getTime() / 1000);
uint32ToByteStreamLE(secs, stream); uint32ToByteStreamLE(secs, stream);
uint64ToByteStreamLE(BigInteger.ZERO, 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. // 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(); byte[] ipBytes = addr.getAddress();
if (ipBytes.length == 4) { if (ipBytes.length == 4) {

View File

@ -18,7 +18,6 @@ package com.google.bitcoin.core;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.math.BigInteger;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
@ -52,7 +51,7 @@ public class VersionMessage extends Message {
super(params, msg, 0); super(params, msg, 0);
} }
public VersionMessage(NetworkParameters params) { public VersionMessage(NetworkParameters params, int newBestHeight) {
super(params); super(params);
clientVersion = NetworkParameters.PROTOCOL_VERSION; clientVersion = NetworkParameters.PROTOCOL_VERSION;
localServices = 0; 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 // 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. // is kind of tricky anyway, so we just put nonsense here for now.
try { try {
myAddr = new PeerAddress(InetAddress.getLocalHost(), params.port); myAddr = new PeerAddress(InetAddress.getLocalHost(), params.port, 0);
theirAddr = new PeerAddress(InetAddress.getLocalHost(), params.port); theirAddr = new PeerAddress(InetAddress.getLocalHost(), params.port, 0);
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
throw new RuntimeException(e); // Cannot happen. throw new RuntimeException(e); // Cannot happen.
} }
subVer = "BitCoinJ 0.1.99"; subVer = "BitCoinJ 0.2";
bestHeight = 0; bestHeight = newBestHeight;
} }
@Override @Override
@ -92,8 +91,9 @@ public class VersionMessage extends Message {
public void bitcoinSerializeToStream(OutputStream buf) throws IOException { public void bitcoinSerializeToStream(OutputStream buf) throws IOException {
Utils.uint32ToByteStreamLE(clientVersion, buf); Utils.uint32ToByteStreamLE(clientVersion, buf);
Utils.uint32ToByteStreamLE(localServices, buf); Utils.uint32ToByteStreamLE(localServices, buf);
Utils.uint32ToByteStreamLE(time >> 32, buf); Utils.uint32ToByteStreamLE(localServices >> 32, buf);
Utils.uint32ToByteStreamLE(time, buf); Utils.uint32ToByteStreamLE(time, buf);
Utils.uint32ToByteStreamLE(time >> 32, buf);
try { try {
// My address. // My address.
myAddr.bitcoinSerializeToStream(buf); myAddr.bitcoinSerializeToStream(buf);

View File

@ -31,11 +31,13 @@ import java.util.concurrent.TimeUnit;
*/ */
public class PingService { public class PingService {
public static void main(String[] args) throws Exception { 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. // Try to read the wallet from storage, create a new one if not possible.
Wallet wallet; Wallet wallet;
final File walletFile = new File("pingservice.wallet"); final File walletFile = new File(filePrefix + ".wallet");
try { try {
wallet = Wallet.loadFromFile(walletFile); wallet = Wallet.loadFromFile(walletFile);
} catch (IOException e) { } catch (IOException e) {
@ -48,11 +50,12 @@ public class PingService {
// Load the block chain, if there is one stored locally. // Load the block chain, if there is one stored locally.
System.out.println("Reading block store from disk"); 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. // Connect to the localhost node.
System.out.println("Connecting ..."); 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); BlockChain chain = new BlockChain(params, wallet, blockStore);
final Peer peer = new Peer(params, conn, chain); final Peer peer = new Peer(params, conn, chain);
peer.start(); peer.start();
@ -61,7 +64,7 @@ public class PingService {
wallet.addEventListener(new WalletEventListener() { wallet.addEventListener(new WalletEventListener() {
public void onCoinsReceived(Wallet w, Transaction tx, BigInteger prevBalance, BigInteger newBalance) { public void onCoinsReceived(Wallet w, Transaction tx, BigInteger prevBalance, BigInteger newBalance) {
// Running on a peer thread. // 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 // 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 // could be inputs from many addresses. So instead we just pick the first and assume they were all
// owned by the same person. // owned by the same person.

View File

@ -46,7 +46,7 @@ public class PrivateKeys {
wallet.addKey(key); wallet.addKey(key);
// Find the transactions that involve those coins. // 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)); BlockChain chain = new BlockChain(params, wallet, new MemoryBlockStore(params));
Peer peer = new Peer(params, conn, chain); Peer peer = new Peer(params, conn, chain);
peer.start(); peer.start();