mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-01-30 23:02: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:
parent
84dcfecb5d
commit
86d7b15f8c
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user