mirror of
https://github.com/Qortal/altcoinj.git
synced 2025-02-12 18:25:51 +00:00
Add relayTxesBeforeFilter flag to VersionMessage, PROTOCOL_VERSION
This adds a relayTxesBeforeFilter flag to VersionMessage, bringing it in line with PROTOCOL_VERSION 70001, and bumps the PROTOCOL_VERSION accordingly.
This commit is contained in:
parent
a0c25aed28
commit
a5f9c3381b
@ -473,6 +473,10 @@ public abstract class Message implements Serializable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean hasMoreBytes() {
|
||||||
|
return cursor < bytes.length;
|
||||||
|
}
|
||||||
|
|
||||||
public static class LazyParseException extends RuntimeException {
|
public static class LazyParseException extends RuntimeException {
|
||||||
private static final long serialVersionUID = 6971943053112975594L;
|
private static final long serialVersionUID = 6971943053112975594L;
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ public class NetworkParameters implements Serializable {
|
|||||||
/**
|
/**
|
||||||
* The protocol version this library implements.
|
* The protocol version this library implements.
|
||||||
*/
|
*/
|
||||||
public static final int PROTOCOL_VERSION = 60001;
|
public static final int PROTOCOL_VERSION = 70001;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The alert signing key originally owned by Satoshi, and now passed on to Gavin along with a few others.
|
* The alert signing key originally owned by Satoshi, and now passed on to Gavin along with a few others.
|
||||||
|
@ -119,10 +119,11 @@ public class Peer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a peer that reads/writes from the given chain. Automatically creates a VersionMessage for you from the
|
* Construct a peer that reads/writes from the given chain. Automatically creates a VersionMessage for you from the
|
||||||
* given software name/version strings, which should be something like "MySimpleTool", "1.0"
|
* given software name/version strings, which should be something like "MySimpleTool", "1.0" and which will tell the
|
||||||
|
* remote node to relay transaction inv messages before it has received a filter.
|
||||||
*/
|
*/
|
||||||
public Peer(NetworkParameters params, AbstractBlockChain blockChain, String thisSoftwareName, String thisSoftwareVersion) {
|
public Peer(NetworkParameters params, AbstractBlockChain blockChain, String thisSoftwareName, String thisSoftwareVersion) {
|
||||||
this(params, blockChain, new VersionMessage(params, blockChain.getBestChainHeight()));
|
this(params, blockChain, new VersionMessage(params, blockChain.getBestChainHeight(), true));
|
||||||
this.versionMessage.appendToSubVer(thisSoftwareName, thisSoftwareVersion, null);
|
this.versionMessage.appendToSubVer(thisSoftwareName, thisSoftwareVersion, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -187,7 +187,8 @@ public class PeerGroup extends AbstractIdleService {
|
|||||||
this.maxConnections = 0;
|
this.maxConnections = 0;
|
||||||
|
|
||||||
int height = chain == null ? 0 : chain.getBestChainHeight();
|
int height = chain == null ? 0 : chain.getBestChainHeight();
|
||||||
this.versionMessage = new VersionMessage(params, height);
|
// We never request that the remote node wait for a bloom filter yet, as we have no wallets
|
||||||
|
this.versionMessage = new VersionMessage(params, height, true);
|
||||||
|
|
||||||
memoryPool = new MemoryPool();
|
memoryPool = new MemoryPool();
|
||||||
|
|
||||||
@ -346,11 +347,22 @@ public class PeerGroup extends AbstractIdleService {
|
|||||||
* @param version
|
* @param version
|
||||||
*/
|
*/
|
||||||
public void setUserAgent(String name, String version, String comments) {
|
public void setUserAgent(String name, String version, String comments) {
|
||||||
VersionMessage ver = new VersionMessage(params, 0);
|
//TODO Check that height is needed here (it wasnt, but it should be, no?)
|
||||||
|
int height = chain == null ? 0 : chain.getBestChainHeight();
|
||||||
|
VersionMessage ver = new VersionMessage(params, height, false);
|
||||||
|
updateVersionMessageRelayTxesBeforeFilter(ver);
|
||||||
ver.appendToSubVer(name, version, comments);
|
ver.appendToSubVer(name, version, comments);
|
||||||
setVersionMessage(ver);
|
setVersionMessage(ver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Updates the relayTxesBeforeFilter flag of ver
|
||||||
|
private synchronized void updateVersionMessageRelayTxesBeforeFilter(VersionMessage ver) {
|
||||||
|
// We will provide the remote node with a bloom filter (ie they shouldn't relay yet)
|
||||||
|
// iff chain == null || !chain.shouldVerifyTransactions() and a wallet is added
|
||||||
|
// Note that the default here means that no tx invs will be received if no wallet is ever added
|
||||||
|
ver.relayTxesBeforeFilter = chain != null && chain.shouldVerifyTransactions() && wallets.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets information that identifies this software to remote nodes. This is a convenience wrapper for creating
|
* Sets information that identifies this software to remote nodes. This is a convenience wrapper for creating
|
||||||
* a new {@link VersionMessage}, calling {@link VersionMessage#appendToSubVer(String, String, String)} on it,
|
* a new {@link VersionMessage}, calling {@link VersionMessage#appendToSubVer(String, String, String)} on it,
|
||||||
@ -535,6 +547,7 @@ public class PeerGroup extends AbstractIdleService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
recalculateFastCatchupAndFilter();
|
recalculateFastCatchupAndFilter();
|
||||||
|
updateVersionMessageRelayTxesBeforeFilter(getVersionMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void recalculateFastCatchupAndFilter() {
|
private synchronized void recalculateFastCatchupAndFilter() {
|
||||||
|
@ -67,6 +67,10 @@ public class VersionMessage extends Message {
|
|||||||
* How many blocks are in the chain, according to the other side.
|
* How many blocks are in the chain, according to the other side.
|
||||||
*/
|
*/
|
||||||
public long bestHeight;
|
public long bestHeight;
|
||||||
|
/**
|
||||||
|
* Whether or not to relay tx invs before a filter is received
|
||||||
|
*/
|
||||||
|
public boolean relayTxesBeforeFilter;
|
||||||
|
|
||||||
public VersionMessage(NetworkParameters params, byte[] msg) throws ProtocolException {
|
public VersionMessage(NetworkParameters params, byte[] msg) throws ProtocolException {
|
||||||
super(params, msg, 0);
|
super(params, msg, 0);
|
||||||
@ -76,7 +80,12 @@ public class VersionMessage extends Message {
|
|||||||
// If you're receiving this on the wire you need to check the protocol version and it will never need to be sent
|
// 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.
|
// back down the wire.
|
||||||
|
|
||||||
|
/** Equivalent to VersionMessage(params, newBestHeight, true) */
|
||||||
public VersionMessage(NetworkParameters params, int newBestHeight) {
|
public VersionMessage(NetworkParameters params, int newBestHeight) {
|
||||||
|
this(params, newBestHeight, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public VersionMessage(NetworkParameters params, int newBestHeight, boolean relayTxesBeforeFilter) {
|
||||||
super(params);
|
super(params);
|
||||||
clientVersion = NetworkParameters.PROTOCOL_VERSION;
|
clientVersion = NetworkParameters.PROTOCOL_VERSION;
|
||||||
localServices = 0;
|
localServices = 0;
|
||||||
@ -94,8 +103,9 @@ public class VersionMessage extends Message {
|
|||||||
}
|
}
|
||||||
subVer = "/BitCoinJ:0.7-SNAPSHOT/";
|
subVer = "/BitCoinJ:0.7-SNAPSHOT/";
|
||||||
bestHeight = newBestHeight;
|
bestHeight = newBestHeight;
|
||||||
|
this.relayTxesBeforeFilter = relayTxesBeforeFilter;
|
||||||
|
|
||||||
length = 84;
|
length = 85;
|
||||||
if (protocolVersion > 31402)
|
if (protocolVersion > 31402)
|
||||||
length += 8;
|
length += 8;
|
||||||
length += subVer == null ? 1 : VarInt.sizeOf(subVer.length()) + subVer.length();
|
length += subVer == null ? 1 : VarInt.sizeOf(subVer.length()) + subVer.length();
|
||||||
@ -123,12 +133,26 @@ public class VersionMessage extends Message {
|
|||||||
// We don't care about the localhost nonce. It's used to detect connecting back to yourself in cases where
|
// We don't care about the localhost nonce. It's used to detect connecting back to yourself in cases where
|
||||||
// there are NATs and proxies in the way. However we don't listen for inbound connections so it's irrelevant.
|
// there are NATs and proxies in the way. However we don't listen for inbound connections so it's irrelevant.
|
||||||
readUint64();
|
readUint64();
|
||||||
|
try {
|
||||||
|
// Initialize default values for flags which may not be sent by old nodes
|
||||||
|
subVer = "";
|
||||||
|
bestHeight = 0;
|
||||||
|
relayTxesBeforeFilter = true;
|
||||||
|
if (!hasMoreBytes())
|
||||||
|
return;
|
||||||
// string subVer (currently "")
|
// string subVer (currently "")
|
||||||
subVer = readStr();
|
subVer = readStr();
|
||||||
|
if (!hasMoreBytes())
|
||||||
|
return;
|
||||||
// int bestHeight (size of known block chain).
|
// int bestHeight (size of known block chain).
|
||||||
bestHeight = readUint32();
|
bestHeight = readUint32();
|
||||||
|
if (!hasMoreBytes())
|
||||||
|
return;
|
||||||
|
relayTxesBeforeFilter = readBytes(1)[0] != 0;
|
||||||
|
} finally {
|
||||||
length = cursor - offset;
|
length = cursor - offset;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bitcoinSerializeToStream(OutputStream buf) throws IOException {
|
public void bitcoinSerializeToStream(OutputStream buf) throws IOException {
|
||||||
@ -158,6 +182,7 @@ public class VersionMessage extends Message {
|
|||||||
buf.write(subVerBytes);
|
buf.write(subVerBytes);
|
||||||
// Size of known block chain.
|
// Size of known block chain.
|
||||||
Utils.uint32ToByteStreamLE(bestHeight, buf);
|
Utils.uint32ToByteStreamLE(bestHeight, buf);
|
||||||
|
buf.write(relayTxesBeforeFilter ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -178,7 +203,8 @@ public class VersionMessage extends Message {
|
|||||||
other.time == time &&
|
other.time == time &&
|
||||||
other.subVer.equals(subVer) &&
|
other.subVer.equals(subVer) &&
|
||||||
other.myAddr.equals(myAddr) &&
|
other.myAddr.equals(myAddr) &&
|
||||||
other.theirAddr.equals(theirAddr);
|
other.theirAddr.equals(theirAddr) &&
|
||||||
|
other.relayTxesBeforeFilter == relayTxesBeforeFilter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -199,7 +225,7 @@ public class VersionMessage extends Message {
|
|||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return (int) bestHeight ^ clientVersion ^ (int) localServices ^ (int) time ^ subVer.hashCode() ^ myAddr.hashCode()
|
return (int) bestHeight ^ clientVersion ^ (int) localServices ^ (int) time ^ subVer.hashCode() ^ myAddr.hashCode()
|
||||||
^ theirAddr.hashCode();
|
^ theirAddr.hashCode() * (relayTxesBeforeFilter ? 1 : 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
@ -212,11 +238,12 @@ public class VersionMessage extends Message {
|
|||||||
sb.append("their addr: ").append(theirAddr).append("\n");
|
sb.append("their addr: ").append(theirAddr).append("\n");
|
||||||
sb.append("sub version: ").append(subVer).append("\n");
|
sb.append("sub version: ").append(subVer).append("\n");
|
||||||
sb.append("best height: ").append(bestHeight).append("\n");
|
sb.append("best height: ").append(bestHeight).append("\n");
|
||||||
|
sb.append("delay tx relay: ").append(relayTxesBeforeFilter).append("\n");
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public VersionMessage duplicate() {
|
public VersionMessage duplicate() {
|
||||||
VersionMessage v = new VersionMessage(params, (int) bestHeight);
|
VersionMessage v = new VersionMessage(params, (int) bestHeight, relayTxesBeforeFilter);
|
||||||
v.clientVersion = clientVersion;
|
v.clientVersion = clientVersion;
|
||||||
v.localServices = localServices;
|
v.localServices = localServices;
|
||||||
v.time = time;
|
v.time = time;
|
||||||
|
@ -55,9 +55,9 @@ public class BitcoinSerializerTest {
|
|||||||
public void testVersion() throws Exception {
|
public void testVersion() throws Exception {
|
||||||
BitcoinSerializer bs = new BitcoinSerializer(NetworkParameters.prodNet(), false);
|
BitcoinSerializer bs = new BitcoinSerializer(NetworkParameters.prodNet(), false);
|
||||||
// the actual data from https://en.bitcoin.it/wiki/Protocol_specification#version
|
// the actual data from https://en.bitcoin.it/wiki/Protocol_specification#version
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(Hex.decode("f9beb4d976657273696f6e0000000000550000009" +
|
ByteArrayInputStream bais = new ByteArrayInputStream(Hex.decode("f9beb4d976657273696f6e0000000000560000009" +
|
||||||
"c7c00000100000000000000e615104d00000000010000000000000000000000000000000000ffff0a000001daf6010000" +
|
"c7c00000100000000000000e615104d00000000010000000000000000000000000000000000ffff0a000001daf6010000" +
|
||||||
"000000000000000000000000000000ffff0a000002208ddd9d202c3ab457130055810100"));
|
"000000000000000000000000000000ffff0a000002208ddd9d202c3ab45713005581010000"));
|
||||||
VersionMessage vm = (VersionMessage)bs.deserialize(bais);
|
VersionMessage vm = (VersionMessage)bs.deserialize(bais);
|
||||||
assertEquals(31900, vm.clientVersion);
|
assertEquals(31900, vm.clientVersion);
|
||||||
assertEquals(1292899814L, vm.time);
|
assertEquals(1292899814L, vm.time);
|
||||||
|
@ -102,10 +102,6 @@ public class MockNetworkConnection implements NetworkConnection {
|
|||||||
this.versionMessage = msg;
|
this.versionMessage = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVersionMessageForHeight(NetworkParameters params, int chainHeight) {
|
|
||||||
versionMessage = new VersionMessage(params, chainHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
public VersionMessage getVersionMessage() {
|
public VersionMessage getVersionMessage() {
|
||||||
if (versionMessage == null) throw new RuntimeException("Need to call setVersionMessage first");
|
if (versionMessage == null) throw new RuntimeException("Need to call setVersionMessage first");
|
||||||
return versionMessage;
|
return versionMessage;
|
||||||
|
@ -0,0 +1,34 @@
|
|||||||
|
package com.google.bitcoin.core;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.spongycastle.util.encoders.Hex;
|
||||||
|
|
||||||
|
public class VersionMessageTest {
|
||||||
|
@Test
|
||||||
|
// Test that we can decode version messages which miss data which some old nodes may not include
|
||||||
|
public void testDecode() throws Exception {
|
||||||
|
NetworkParameters params = NetworkParameters.unitTests();
|
||||||
|
|
||||||
|
VersionMessage ver = new VersionMessage(params, Hex.decode("71110100000000000000000048e5e95000000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d0000000000000000172f426974436f696e4a3a302e372d534e415053484f542f0004000000"));
|
||||||
|
assertTrue(!ver.relayTxesBeforeFilter);
|
||||||
|
assertTrue(ver.bestHeight == 1024);
|
||||||
|
assertTrue(ver.subVer.equals("/BitCoinJ:0.7-SNAPSHOT/"));
|
||||||
|
|
||||||
|
ver = new VersionMessage(params, Hex.decode("71110100000000000000000048e5e95000000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d0000000000000000172f426974436f696e4a3a302e372d534e415053484f542f00040000"));
|
||||||
|
assertTrue(ver.relayTxesBeforeFilter);
|
||||||
|
assertTrue(ver.bestHeight == 1024);
|
||||||
|
assertTrue(ver.subVer.equals("/BitCoinJ:0.7-SNAPSHOT/"));
|
||||||
|
|
||||||
|
ver = new VersionMessage(params, Hex.decode("71110100000000000000000048e5e95000000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d0000000000000000172f426974436f696e4a3a302e372d534e415053484f542f"));
|
||||||
|
assertTrue(ver.relayTxesBeforeFilter);
|
||||||
|
assertTrue(ver.bestHeight == 0);
|
||||||
|
assertTrue(ver.subVer.equals("/BitCoinJ:0.7-SNAPSHOT/"));
|
||||||
|
|
||||||
|
ver = new VersionMessage(params, Hex.decode("71110100000000000000000048e5e95000000000000000000000000000000000000000000000ffff7f000001479d000000000000000000000000000000000000ffff7f000001479d0000000000000000"));
|
||||||
|
assertTrue(ver.relayTxesBeforeFilter);
|
||||||
|
assertTrue(ver.bestHeight == 0);
|
||||||
|
assertTrue(ver.subVer.equals(""));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user