3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-31 07:12:17 +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
* 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();

View File

@ -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) {

View File

@ -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);

View File

@ -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.

View File

@ -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();