mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2025-02-23 14:40:40 +01:00
Support BIP155 addrv2
messages.
This commit is contained in:
parent
9e9b6b4c74
commit
d511effbce
16 changed files with 612 additions and 155 deletions
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
* Copyright 2014 Andreas Schildbach
|
||||
* Copyright by the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -19,74 +18,18 @@ package org.bitcoinj.core;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>Represents an "addr" message on the P2P network, which contains broadcast IP addresses of other peers. This is
|
||||
* one of the ways peers can find each other without using the DNS or IRC discovery mechanisms. However storing and
|
||||
* using addr messages is not presently implemented.</p>
|
||||
*
|
||||
* <p>Instances of this class are not safe for use by multiple threads.</p>
|
||||
*/
|
||||
public class AddressMessage extends Message {
|
||||
public abstract class AddressMessage extends Message {
|
||||
|
||||
private static final long MAX_ADDRESSES = 1000;
|
||||
private List<PeerAddress> addresses;
|
||||
protected static final long MAX_ADDRESSES = 1000;
|
||||
protected List<PeerAddress> addresses;
|
||||
|
||||
/**
|
||||
* Construct a new 'addr' message.
|
||||
* @param params NetworkParameters object.
|
||||
* @param offset The location of the first payload byte within the array.
|
||||
* @param serializer the serializer to use for this block.
|
||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
AddressMessage(NetworkParameters params, byte[] payload, int offset, MessageSerializer serializer, int length) throws ProtocolException {
|
||||
super(params, payload, offset, serializer, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new 'addr' message.
|
||||
* @param params NetworkParameters object.
|
||||
* @param serializer the serializer to use for this block.
|
||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
AddressMessage(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length) throws ProtocolException {
|
||||
super(params, payload, 0, serializer, length);
|
||||
}
|
||||
|
||||
AddressMessage(NetworkParameters params, byte[] payload, int offset) throws ProtocolException {
|
||||
super(params, payload, offset, params.getDefaultSerializer(), UNKNOWN_LENGTH);
|
||||
}
|
||||
|
||||
AddressMessage(NetworkParameters params, byte[] payload) throws ProtocolException {
|
||||
super(params, payload, 0, params.getDefaultSerializer(), UNKNOWN_LENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse() throws ProtocolException {
|
||||
VarInt numAddressesVarInt = readVarInt();
|
||||
int numAddresses = numAddressesVarInt.intValue();
|
||||
// Guard against ultra large messages that will crash us.
|
||||
if (numAddresses > MAX_ADDRESSES)
|
||||
throw new ProtocolException("Address message too large.");
|
||||
addresses = new ArrayList<>((int) numAddresses);
|
||||
int protocolVersion = serializer.getProtocolVersion();
|
||||
for (int i = 0; i < numAddresses; i++) {
|
||||
PeerAddress addr = new PeerAddress(params, payload, cursor, this, serializer);
|
||||
addresses.add(addr);
|
||||
cursor += addr.getMessageSize();
|
||||
}
|
||||
length = numAddressesVarInt.getSizeInBytes();
|
||||
// The 4 byte difference is the uint32 timestamp that was introduced in version 31402
|
||||
length += addresses.size() * (protocolVersion > 31402 ? PeerAddress.MESSAGE_SIZE : PeerAddress.MESSAGE_SIZE - 4);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bitcoinSerializeToStream(OutputStream stream) throws IOException {
|
||||
if (addresses == null)
|
||||
|
@ -97,35 +40,20 @@ public class AddressMessage extends Message {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return An unmodifiableList view of the backing List of addresses. Addresses contained within the list may be safely modified.
|
||||
*/
|
||||
public List<PeerAddress> getAddresses() {
|
||||
return Collections.unmodifiableList(addresses);
|
||||
}
|
||||
|
||||
public void addAddress(PeerAddress address) {
|
||||
unCache();
|
||||
address.setParent(this);
|
||||
addresses.add(address);
|
||||
if (length == UNKNOWN_LENGTH)
|
||||
getMessageSize();
|
||||
else
|
||||
length += address.getMessageSize();
|
||||
}
|
||||
public abstract void addAddress(PeerAddress address);
|
||||
|
||||
public void removeAddress(int index) {
|
||||
unCache();
|
||||
PeerAddress address = addresses.remove(index);
|
||||
address.setParent(null);
|
||||
if (length == UNKNOWN_LENGTH)
|
||||
getMessageSize();
|
||||
else
|
||||
length -= address.getMessageSize();
|
||||
length = UNKNOWN_LENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "addr: " + Utils.SPACE_JOINER.join(addresses);
|
||||
/**
|
||||
* @return An unmodifiableList view of the backing List of addresses. Addresses contained within the list may be
|
||||
* safely modified.
|
||||
*/
|
||||
public List<PeerAddress> getAddresses() {
|
||||
return Collections.unmodifiableList(addresses);
|
||||
}
|
||||
}
|
||||
|
|
97
core/src/main/java/org/bitcoinj/core/AddressV1Message.java
Normal file
97
core/src/main/java/org/bitcoinj/core/AddressV1Message.java
Normal file
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright 2011 Google Inc.
|
||||
* Copyright 2014 Andreas Schildbach
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoinj.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* <p>Represents an "addr" message on the P2P network, which contains broadcast IP addresses of other peers. This is
|
||||
* one of the ways peers can find each other without using the DNS or IRC discovery mechanisms. However storing and
|
||||
* using addr messages is not presently implemented.</p>
|
||||
*
|
||||
* <p>Instances of this class are not safe for use by multiple threads.</p>
|
||||
*/
|
||||
public class AddressV1Message extends AddressMessage {
|
||||
|
||||
/**
|
||||
* Construct a new 'addr' message.
|
||||
* @param params NetworkParameters object.
|
||||
* @param offset The location of the first payload byte within the array.
|
||||
* @param serializer the serializer to use for this block.
|
||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
AddressV1Message(NetworkParameters params, byte[] payload, int offset, MessageSerializer serializer, int length) throws ProtocolException {
|
||||
super(params, payload, offset, serializer, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new 'addr' message.
|
||||
* @param params NetworkParameters object.
|
||||
* @param serializer the serializer to use for this block.
|
||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
AddressV1Message(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length) throws ProtocolException {
|
||||
super(params, payload, 0, serializer, length);
|
||||
}
|
||||
|
||||
AddressV1Message(NetworkParameters params, byte[] payload, int offset) throws ProtocolException {
|
||||
super(params, payload, offset, params.getDefaultSerializer(), UNKNOWN_LENGTH);
|
||||
}
|
||||
|
||||
AddressV1Message(NetworkParameters params, byte[] payload) throws ProtocolException {
|
||||
super(params, payload, 0, params.getDefaultSerializer(), UNKNOWN_LENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse() throws ProtocolException {
|
||||
final VarInt numAddressesVarInt = readVarInt();
|
||||
int numAddresses = numAddressesVarInt.intValue();
|
||||
// Guard against ultra large messages that will crash us.
|
||||
if (numAddresses > MAX_ADDRESSES)
|
||||
throw new ProtocolException("Address message too large.");
|
||||
addresses = new ArrayList<>(numAddresses);
|
||||
MessageSerializer serializer = this.serializer.withProtocolVersion(1);
|
||||
length = numAddressesVarInt.getSizeInBytes();
|
||||
for (int i = 0; i < numAddresses; i++) {
|
||||
PeerAddress addr = new PeerAddress(params, payload, cursor, this, serializer);
|
||||
addresses.add(addr);
|
||||
cursor += addr.getMessageSize();
|
||||
length += addr.getMessageSize();
|
||||
}
|
||||
}
|
||||
|
||||
public void addAddress(PeerAddress address) {
|
||||
int protocolVersion = address.serializer.getProtocolVersion();
|
||||
if (protocolVersion != 1)
|
||||
throw new IllegalStateException("invalid protocolVersion: " + protocolVersion);
|
||||
|
||||
unCache();
|
||||
address.setParent(this);
|
||||
addresses.add(address);
|
||||
length = UNKNOWN_LENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "addr: " + Utils.SPACE_JOINER.join(addresses);
|
||||
}
|
||||
}
|
94
core/src/main/java/org/bitcoinj/core/AddressV2Message.java
Normal file
94
core/src/main/java/org/bitcoinj/core/AddressV2Message.java
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright by the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoinj.core;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* <p>Represents an "addrv2" message on the P2P network, which contains broadcast IP addresses of other peers. This is
|
||||
* one of the ways peers can find each other without using the DNS or IRC discovery mechanisms. However storing and
|
||||
* using addrv2 messages is not presently implemented.</p>
|
||||
*
|
||||
* <p>See <a href="https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki">BIP155</a> for details.</p>
|
||||
*
|
||||
* <p>Instances of this class are not safe for use by multiple threads.</p>
|
||||
*/
|
||||
public class AddressV2Message extends AddressMessage {
|
||||
|
||||
/**
|
||||
* Construct a new 'addrv2' message.
|
||||
* @param params NetworkParameters object.
|
||||
* @param offset The location of the first payload byte within the array.
|
||||
* @param serializer the serializer to use for this block.
|
||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
AddressV2Message(NetworkParameters params, byte[] payload, int offset, MessageSerializer serializer, int length) throws ProtocolException {
|
||||
super(params, payload, offset, serializer, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new 'addrv2' message.
|
||||
* @param params NetworkParameters object.
|
||||
* @param serializer the serializer to use for this block.
|
||||
* @param length The length of message if known. Usually this is provided when deserializing of the wire
|
||||
* as the length will be provided as part of the header. If unknown then set to Message.UNKNOWN_LENGTH
|
||||
* @throws ProtocolException
|
||||
*/
|
||||
AddressV2Message(NetworkParameters params, byte[] payload, MessageSerializer serializer, int length) throws ProtocolException {
|
||||
super(params, payload, 0, serializer, length);
|
||||
}
|
||||
|
||||
AddressV2Message(NetworkParameters params, byte[] payload) throws ProtocolException {
|
||||
super(params, payload, 0, params.getDefaultSerializer(), UNKNOWN_LENGTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse() throws ProtocolException {
|
||||
final VarInt numAddressesVarInt = readVarInt();
|
||||
int numAddresses = numAddressesVarInt.intValue();
|
||||
// Guard against ultra large messages that will crash us.
|
||||
if (numAddresses > MAX_ADDRESSES)
|
||||
throw new ProtocolException("Address message too large.");
|
||||
addresses = new ArrayList<>(numAddresses);
|
||||
MessageSerializer serializer = this.serializer.withProtocolVersion(2);
|
||||
length = numAddressesVarInt.getSizeInBytes();
|
||||
for (int i = 0; i < numAddresses; i++) {
|
||||
PeerAddress addr = new PeerAddress(params, payload, cursor, this, serializer);
|
||||
addresses.add(addr);
|
||||
cursor += addr.getMessageSize();
|
||||
length += addr.getMessageSize();
|
||||
}
|
||||
}
|
||||
|
||||
public void addAddress(PeerAddress address) {
|
||||
int protocolVersion = address.serializer.getProtocolVersion();
|
||||
if (protocolVersion != 2)
|
||||
throw new IllegalStateException("invalid protocolVersion: " + protocolVersion);
|
||||
|
||||
unCache();
|
||||
address.setParent(this);
|
||||
addresses.add(address);
|
||||
length = UNKNOWN_LENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "addrv2: " + Utils.SPACE_JOINER.join(addresses);
|
||||
}
|
||||
}
|
|
@ -59,13 +59,15 @@ public class BitcoinSerializer extends MessageSerializer {
|
|||
names.put(Block.class, "block");
|
||||
names.put(GetDataMessage.class, "getdata");
|
||||
names.put(Transaction.class, "tx");
|
||||
names.put(AddressMessage.class, "addr");
|
||||
names.put(AddressV1Message.class, "addr");
|
||||
names.put(AddressV2Message.class, "addrv2");
|
||||
names.put(Ping.class, "ping");
|
||||
names.put(Pong.class, "pong");
|
||||
names.put(VersionAck.class, "verack");
|
||||
names.put(GetBlocksMessage.class, "getblocks");
|
||||
names.put(GetHeadersMessage.class, "getheaders");
|
||||
names.put(GetAddrMessage.class, "getaddr");
|
||||
names.put(SendAddrV2Message.class, "sendaddrv2");
|
||||
names.put(HeadersMessage.class, "headers");
|
||||
names.put(BloomFilter.class, "filterload");
|
||||
names.put(FilteredBlock.class, "merkleblock");
|
||||
|
@ -231,8 +233,12 @@ public class BitcoinSerializer extends MessageSerializer {
|
|||
return new GetHeadersMessage(params, payloadBytes);
|
||||
} else if (command.equals("tx")) {
|
||||
return makeTransaction(payloadBytes, 0, length, hash);
|
||||
} else if (command.equals("sendaddrv2")) {
|
||||
return new SendAddrV2Message(params);
|
||||
} else if (command.equals("addr")) {
|
||||
return makeAddressMessage(payloadBytes, length);
|
||||
return makeAddressV1Message(payloadBytes, length);
|
||||
} else if (command.equals("addrv2")) {
|
||||
return makeAddressV2Message(payloadBytes, length);
|
||||
} else if (command.equals("ping")) {
|
||||
return new Ping(params, payloadBytes);
|
||||
} else if (command.equals("pong")) {
|
||||
|
@ -272,8 +278,17 @@ public class BitcoinSerializer extends MessageSerializer {
|
|||
* serialization format support.
|
||||
*/
|
||||
@Override
|
||||
public AddressMessage makeAddressMessage(byte[] payloadBytes, int length) throws ProtocolException {
|
||||
return new AddressMessage(params, payloadBytes, this, length);
|
||||
public AddressV1Message makeAddressV1Message(byte[] payloadBytes, int length) throws ProtocolException {
|
||||
return new AddressV1Message(params, payloadBytes, this, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make an address message from the payload. Extension point for alternative
|
||||
* serialization format support.
|
||||
*/
|
||||
@Override
|
||||
public AddressV2Message makeAddressV2Message(byte[] payloadBytes, int length) throws ProtocolException {
|
||||
return new AddressV2Message(params, payloadBytes, this, length);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -64,7 +64,12 @@ class DummySerializer extends MessageSerializer {
|
|||
}
|
||||
|
||||
@Override
|
||||
public AddressMessage makeAddressMessage(byte[] payloadBytes, int length) throws UnsupportedOperationException {
|
||||
public AddressV1Message makeAddressV1Message(byte[] payloadBytes, int length) throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AddressV2Message makeAddressV2Message(byte[] payloadBytes, int length) throws UnsupportedOperationException {
|
||||
throw new UnsupportedOperationException(DEFAULT_EXCEPTION_MESSAGE);
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,13 @@ public abstract class MessageSerializer {
|
|||
* Make an address message from the payload. Extension point for alternative
|
||||
* serialization format support.
|
||||
*/
|
||||
public abstract AddressMessage makeAddressMessage(byte[] payloadBytes, int length) throws ProtocolException, UnsupportedOperationException;
|
||||
public abstract AddressV1Message makeAddressV1Message(byte[] payloadBytes, int length) throws ProtocolException, UnsupportedOperationException;
|
||||
|
||||
/**
|
||||
* Make an address message from the payload. Extension point for alternative
|
||||
* serialization format support.
|
||||
*/
|
||||
public abstract AddressV2Message makeAddressV2Message(byte[] payloadBytes, int length) throws ProtocolException, UnsupportedOperationException;
|
||||
|
||||
/**
|
||||
* Make a block from the payload, using an offset of zero and the payload
|
||||
|
|
|
@ -442,7 +442,7 @@ public class Peer extends PeerSocketHandler {
|
|||
}
|
||||
|
||||
// No further communication is possible until version handshake is complete.
|
||||
if (!(m instanceof VersionMessage || m instanceof VersionAck
|
||||
if (!(m instanceof VersionMessage || m instanceof VersionAck || m instanceof SendAddrV2Message
|
||||
|| (versionHandshakeFuture.isDone() && !versionHandshakeFuture.isCancelled())))
|
||||
throw new ProtocolException(
|
||||
"Received " + m.getClass().getSimpleName() + " before version handshake is complete.");
|
||||
|
@ -544,6 +544,8 @@ public class Peer extends PeerSocketHandler {
|
|||
// In this case, it's a protocol violation.
|
||||
throw new ProtocolException("Peer reports invalid best height: " + peerVersionMessage.bestHeight);
|
||||
// Now it's our turn ...
|
||||
// Send a sendaddrv2 message, indicating that we prefer to receive addrv2 messages.
|
||||
sendMessage(new SendAddrV2Message(params));
|
||||
// Send an ACK message stating we accept the peers protocol version.
|
||||
sendMessage(new VersionAck());
|
||||
if (log.isDebugEnabled())
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.bitcoinj.core;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
@ -31,13 +33,13 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
/**
|
||||
* <p>A PeerAddress holds an IP address and port number representing the network location of
|
||||
* a peer in the Bitcoin P2P network. It exists primarily for serialization purposes.</p>
|
||||
*
|
||||
* <p>This class abuses the protocol version contained in its serializer. It can only contain 0 (format within
|
||||
* {@link VersionMessage}), 1 ({@link AddressV1Message}) or 2 ({@link AddressV2Message}).</p>
|
||||
*
|
||||
* <p>Instances of this class are not safe for use by multiple threads.</p>
|
||||
*/
|
||||
public class PeerAddress extends ChildMessage {
|
||||
|
||||
static final int MESSAGE_SIZE = 30;
|
||||
|
||||
private InetAddress addr;
|
||||
private String hostname; // Used for .onion addresses
|
||||
private int port;
|
||||
|
@ -65,14 +67,21 @@ public class PeerAddress extends ChildMessage {
|
|||
this.port = port;
|
||||
setSerializer(serializer);
|
||||
this.services = services;
|
||||
length = isSerializeTime() ? MESSAGE_SIZE : MESSAGE_SIZE - 4;
|
||||
this.time = Utils.currentTimeSeconds();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a peer address from the given IP address, port and services. Version number is default for the given parameters.
|
||||
*/
|
||||
public PeerAddress(NetworkParameters params, InetAddress addr, int port, BigInteger services) {
|
||||
this(params, addr, port, services, params.getDefaultSerializer().withProtocolVersion(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a peer address from the given IP address and port. Version number is default for the given parameters.
|
||||
*/
|
||||
public PeerAddress(NetworkParameters params, InetAddress addr, int port) {
|
||||
this(params, addr, port, BigInteger.ZERO, params.getDefaultSerializer());
|
||||
this(params, addr, port, BigInteger.ZERO);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -99,6 +108,7 @@ public class PeerAddress extends ChildMessage {
|
|||
this.hostname = hostname;
|
||||
this.port = port;
|
||||
this.services = BigInteger.ZERO;
|
||||
this.time = Utils.currentTimeSeconds();
|
||||
}
|
||||
|
||||
public static PeerAddress localhost(NetworkParameters params) {
|
||||
|
@ -107,54 +117,110 @@ public class PeerAddress extends ChildMessage {
|
|||
|
||||
@Override
|
||||
protected void bitcoinSerializeToStream(OutputStream stream) throws IOException {
|
||||
if (isSerializeTime()) {
|
||||
//TODO this appears to be dynamic because the client only ever sends out it's own address
|
||||
//so assumes itself to be up. For a fuller implementation this needs to be dynamic only if
|
||||
//the address refers to this client.
|
||||
int secs = (int) (Utils.currentTimeSeconds());
|
||||
Utils.uint32ToByteStreamLE(secs, stream);
|
||||
int protocolVersion = serializer.getProtocolVersion();
|
||||
if (protocolVersion < 0 || protocolVersion > 2)
|
||||
throw new IllegalStateException("invalid protocolVersion: " + protocolVersion);
|
||||
|
||||
if (protocolVersion >= 1) {
|
||||
Utils.uint32ToByteStreamLE(time, stream);
|
||||
}
|
||||
Utils.uint64ToByteStreamLE(services, 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) {
|
||||
byte[] v6addr = new byte[16];
|
||||
System.arraycopy(ipBytes, 0, v6addr, 12, 4);
|
||||
v6addr[10] = (byte) 0xFF;
|
||||
v6addr[11] = (byte) 0xFF;
|
||||
ipBytes = v6addr;
|
||||
if (protocolVersion == 2) {
|
||||
stream.write(new VarInt(services.longValue()).encode());
|
||||
if (addr != null) {
|
||||
if (addr instanceof Inet4Address) {
|
||||
stream.write(0x01);
|
||||
stream.write(new VarInt(4).encode());
|
||||
stream.write(addr.getAddress());
|
||||
} else if (addr instanceof Inet6Address) {
|
||||
stream.write(0x02);
|
||||
stream.write(new VarInt(16).encode());
|
||||
stream.write(addr.getAddress());
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
} else {
|
||||
Utils.uint64ToByteStreamLE(services, stream); // nServices.
|
||||
if (addr != null) {
|
||||
// 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) {
|
||||
byte[] v6addr = new byte[16];
|
||||
System.arraycopy(ipBytes, 0, v6addr, 12, 4);
|
||||
v6addr[10] = (byte) 0xFF;
|
||||
v6addr[11] = (byte) 0xFF;
|
||||
ipBytes = v6addr;
|
||||
}
|
||||
stream.write(ipBytes);
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
stream.write(ipBytes);
|
||||
// And write out the port. Unlike the rest of the protocol, address and port is in big endian byte order.
|
||||
Utils.uint16ToByteStreamBE(port, stream);
|
||||
}
|
||||
|
||||
private boolean isSerializeTime() {
|
||||
return serializer.getProtocolVersion() >= 31402 && !(parent instanceof VersionMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void parse() throws ProtocolException {
|
||||
// Format of a serialized address:
|
||||
// uint32 timestamp
|
||||
// uint64 services (flags determining what the node can do)
|
||||
// 16 bytes ip address
|
||||
// 2 bytes port num
|
||||
if (isSerializeTime())
|
||||
int protocolVersion = serializer.getProtocolVersion();
|
||||
if (protocolVersion < 0 || protocolVersion > 2)
|
||||
throw new IllegalStateException("invalid protocolVersion: " + protocolVersion);
|
||||
|
||||
length = 0;
|
||||
if (protocolVersion >= 1) {
|
||||
time = readUint32();
|
||||
else
|
||||
length += 4;
|
||||
} else {
|
||||
time = -1;
|
||||
services = readUint64();
|
||||
byte[] addrBytes = readBytes(16);
|
||||
try {
|
||||
addr = InetAddress.getByAddress(addrBytes);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RuntimeException(e); // Cannot happen.
|
||||
}
|
||||
if (protocolVersion == 2) {
|
||||
VarInt servicesVarInt = readVarInt();
|
||||
length += servicesVarInt.getSizeInBytes();
|
||||
services = BigInteger.valueOf(servicesVarInt.longValue());
|
||||
int networkId = readByte();
|
||||
length += 1;
|
||||
byte[] addrBytes = readByteArray();
|
||||
int addrLen = addrBytes.length;
|
||||
length += VarInt.sizeOf(addrLen) + addrLen;
|
||||
if (networkId == 0x01) {
|
||||
// IPv4
|
||||
if (addrLen != 4)
|
||||
throw new ProtocolException("invalid length of IPv4 address: " + addrLen);
|
||||
addr = getByAddress(addrBytes);
|
||||
hostname = null;
|
||||
} else if (networkId == 0x02) {
|
||||
// IPv6
|
||||
if (addrLen != 16)
|
||||
throw new ProtocolException("invalid length of IPv6 address: " + addrLen);
|
||||
addr = getByAddress(addrBytes);
|
||||
hostname = null;
|
||||
} else {
|
||||
// ignore unknown network IDs
|
||||
addr = null;
|
||||
hostname = null;
|
||||
}
|
||||
} else {
|
||||
services = readUint64();
|
||||
length += 8;
|
||||
byte[] addrBytes = readBytes(16);
|
||||
length += 16;
|
||||
addr = getByAddress(addrBytes);
|
||||
hostname = null;
|
||||
}
|
||||
port = Utils.readUint16BE(payload, cursor);
|
||||
cursor += 2;
|
||||
// The 4 byte difference is the uint32 timestamp that was introduced in version 31402
|
||||
length = isSerializeTime() ? MESSAGE_SIZE : MESSAGE_SIZE - 4;
|
||||
length += 2;
|
||||
}
|
||||
|
||||
private static InetAddress getByAddress(byte[] addrBytes) {
|
||||
try {
|
||||
return InetAddress.getByAddress(addrBytes);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new RuntimeException(e); // Cannot happen.
|
||||
}
|
||||
}
|
||||
|
||||
public String getHostname() {
|
||||
|
|
31
core/src/main/java/org/bitcoinj/core/SendAddrV2Message.java
Normal file
31
core/src/main/java/org/bitcoinj/core/SendAddrV2Message.java
Normal file
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright by the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoinj.core;
|
||||
|
||||
/**
|
||||
* <p>Represents the {@code sendaddrv2} P2P protocol message, which indicates that a node can understand and prefers
|
||||
* to receive {@code addrv2] messages instead of {@code addr} messages.</p>
|
||||
*
|
||||
* <p>See <a href="https://github.com/bitcoin/bips/blob/master/bip-0155.mediawiki">BIP155</a> for details.</p>
|
||||
*
|
||||
* <p>Instances of this class are not safe for use by multiple threads.</p>
|
||||
*/
|
||||
public class SendAddrV2Message extends EmptyMessage {
|
||||
public SendAddrV2Message(NetworkParameters params) {
|
||||
super(params);
|
||||
}
|
||||
}
|
|
@ -112,6 +112,7 @@ public class VersionMessage extends Message {
|
|||
// Note that the Bitcoin Core 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.
|
||||
InetAddress localhost = InetAddresses.forString("127.0.0.1");
|
||||
MessageSerializer serializer = this.serializer.withProtocolVersion(0);
|
||||
receivingAddr = new PeerAddress(params, localhost, params.getPort(), BigInteger.ZERO, serializer);
|
||||
receivingAddr.setParent(this);
|
||||
fromAddr = new PeerAddress(params, localhost, params.getPort(), BigInteger.ZERO, serializer);
|
||||
|
@ -119,9 +120,6 @@ public class VersionMessage extends Message {
|
|||
subVer = LIBRARY_SUBVER;
|
||||
bestHeight = newBestHeight;
|
||||
relayTxesBeforeFilter = true;
|
||||
|
||||
length = 4 + 8 + 8 + receivingAddr.getMessageSize() + fromAddr.getMessageSize() + 8
|
||||
+ VarInt.sizeOf(subVer.length()) + subVer.length() + 4 + 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -805,7 +805,7 @@ public class WalletProtobufSerializer {
|
|||
}
|
||||
int port = proto.getPort();
|
||||
BigInteger services = BigInteger.valueOf(proto.getServices());
|
||||
PeerAddress address = new PeerAddress(params, ip, port, services, params.getDefaultSerializer());
|
||||
PeerAddress address = new PeerAddress(params, ip, port, services);
|
||||
confidence.markBroadcastBy(address);
|
||||
}
|
||||
if (confidenceProto.hasLastBroadcastedAt())
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright by the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoinj.core;
|
||||
|
||||
import org.bitcoinj.params.UnitTestParams;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.util.List;
|
||||
|
||||
import static org.bitcoinj.core.Utils.HEX;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class AddressV1MessageTest {
|
||||
|
||||
private static final NetworkParameters UNITTEST = UnitTestParams.get();
|
||||
// mostly copied from src/test/netbase_tests.cpp#stream_addrv1_hex
|
||||
private static final String MESSAGE_HEX =
|
||||
"03" // number of entries
|
||||
|
||||
+ "61bc6649" // time, Fri Jan 9 02:54:25 UTC 2009
|
||||
+ "0000000000000000" // service flags, NODE_NONE
|
||||
+ "00000000000000000000ffff00000001" // address, fixed 16 bytes (IPv4 embedded in IPv6)
|
||||
+ "0000" // port
|
||||
|
||||
+ "79627683" // time, Tue Nov 22 11:22:33 UTC 2039
|
||||
+ "0100000000000000" // service flags, NODE_NETWORK
|
||||
+ "00000000000000000000000000000001" // address, fixed 16 bytes (IPv6)
|
||||
+ "00f1" // port
|
||||
|
||||
+ "ffffffff" // time, Sun Feb 7 06:28:15 UTC 2106
|
||||
+ "4804000000000000" // service flags, NODE_WITNESS | NODE_COMPACT_FILTERS | NODE_NETWORK_LIMITED
|
||||
+ "00000000000000000000000000000001" // address, fixed 16 bytes (IPv6)
|
||||
+ "f1f2"; // port
|
||||
|
||||
@Test
|
||||
public void roundtrip() {
|
||||
AddressMessage message = new AddressV1Message(UNITTEST, HEX.decode(MESSAGE_HEX));
|
||||
|
||||
List<PeerAddress> addresses = message.getAddresses();
|
||||
assertEquals(3, addresses.size());
|
||||
PeerAddress a0 = addresses.get(0);
|
||||
assertEquals("2009-01-09T02:54:25Z", Utils.dateTimeFormat(a0.getTime() * 1000));
|
||||
assertEquals(0, a0.getServices().intValue());
|
||||
assertTrue(a0.getAddr() instanceof Inet4Address);
|
||||
assertEquals("0.0.0.1", a0.getAddr().getHostAddress());
|
||||
assertNull(a0.getHostname());
|
||||
assertEquals(0, a0.getPort());
|
||||
PeerAddress a1 = addresses.get(1);
|
||||
assertEquals("2039-11-22T11:22:33Z", Utils.dateTimeFormat(a1.getTime() * 1000));
|
||||
assertEquals(VersionMessage.NODE_NETWORK, a1.getServices().intValue());
|
||||
assertTrue(a1.getAddr() instanceof Inet6Address);
|
||||
assertEquals("0:0:0:0:0:0:0:1", a1.getAddr().getHostAddress());
|
||||
assertNull(a1.getHostname());
|
||||
assertEquals(0xf1, a1.getPort());
|
||||
PeerAddress a2 = addresses.get(2);
|
||||
assertEquals("2106-02-07T06:28:15Z", Utils.dateTimeFormat(a2.getTime() * 1000));
|
||||
assertEquals(VersionMessage.NODE_WITNESS | 1 << 6 /* NODE_COMPACT_FILTERS */
|
||||
| VersionMessage.NODE_NETWORK_LIMITED, a2.getServices().intValue());
|
||||
assertTrue(a2.getAddr() instanceof Inet6Address);
|
||||
assertEquals("0:0:0:0:0:0:0:1", a2.getAddr().getHostAddress());
|
||||
assertNull(a2.getHostname());
|
||||
assertEquals(0xf1f2, a2.getPort());
|
||||
|
||||
assertEquals(MESSAGE_HEX, HEX.encode(message.bitcoinSerialize()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright by the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.bitcoinj.core;
|
||||
|
||||
import org.bitcoinj.params.UnitTestParams;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.util.List;
|
||||
|
||||
import static org.bitcoinj.core.Utils.HEX;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class AddressV2MessageTest {
|
||||
|
||||
private static final NetworkParameters UNITTEST = UnitTestParams.get();
|
||||
// mostly copied from src/test/netbase_tests.cpp#stream_addrv2_hex
|
||||
private static final String MESSAGE_HEX =
|
||||
"03" // number of entries
|
||||
|
||||
+ "61bc6649" // time, Fri Jan 9 02:54:25 UTC 2009
|
||||
+ "00" // service flags, COMPACTSIZE(NODE_NONE)
|
||||
+ "01" // network id, IPv4
|
||||
+ "04" // address length, COMPACTSIZE(4)
|
||||
+ "00000001" // address
|
||||
+ "0000" // port
|
||||
|
||||
+ "79627683" // time, Tue Nov 22 11:22:33 UTC 2039
|
||||
+ "01" // service flags, COMPACTSIZE(NODE_NETWORK)
|
||||
+ "02" // network id, IPv6
|
||||
+ "10" // address length, COMPACTSIZE(16)
|
||||
+ "00000000000000000000000000000001" // address
|
||||
+ "00f1" // port
|
||||
|
||||
+ "ffffffff" // time, Sun Feb 7 06:28:15 UTC 2106
|
||||
+ "fd4804" // service flags, COMPACTSIZE(NODE_WITNESS | NODE_COMPACT_FILTERS | NODE_NETWORK_LIMITED)
|
||||
+ "02" // network id, IPv6
|
||||
+ "10" // address length, COMPACTSIZE(16)
|
||||
+ "00000000000000000000000000000001" // address
|
||||
+ "f1f2"; // port
|
||||
|
||||
@Test
|
||||
public void roundtrip() {
|
||||
AddressMessage message = new AddressV2Message(UNITTEST, HEX.decode(MESSAGE_HEX));
|
||||
|
||||
List<PeerAddress> addresses = message.getAddresses();
|
||||
assertEquals(3, addresses.size());
|
||||
PeerAddress a0 = addresses.get(0);
|
||||
assertEquals("2009-01-09T02:54:25Z", Utils.dateTimeFormat(a0.getTime() * 1000));
|
||||
assertEquals(0, a0.getServices().intValue());
|
||||
assertTrue(a0.getAddr() instanceof Inet4Address);
|
||||
assertEquals("0.0.0.1", a0.getAddr().getHostAddress());
|
||||
assertNull(a0.getHostname());
|
||||
assertEquals(0, a0.getPort());
|
||||
PeerAddress a1 = addresses.get(1);
|
||||
assertEquals("2039-11-22T11:22:33Z", Utils.dateTimeFormat(a1.getTime() * 1000));
|
||||
assertEquals(VersionMessage.NODE_NETWORK, a1.getServices().intValue());
|
||||
assertTrue(a1.getAddr() instanceof Inet6Address);
|
||||
assertEquals("0:0:0:0:0:0:0:1", a1.getAddr().getHostAddress());
|
||||
assertNull(a1.getHostname());
|
||||
assertEquals(0xf1, a1.getPort());
|
||||
PeerAddress a2 = addresses.get(2);
|
||||
assertEquals("2106-02-07T06:28:15Z", Utils.dateTimeFormat(a2.getTime() * 1000));
|
||||
assertEquals(VersionMessage.NODE_WITNESS | 1 << 6 /* NODE_COMPACT_FILTERS */
|
||||
| VersionMessage.NODE_NETWORK_LIMITED, a2.getServices().intValue());
|
||||
assertTrue(a2.getAddr() instanceof Inet6Address);
|
||||
assertEquals("0:0:0:0:0:0:0:1", a2.getAddr().getHostAddress());
|
||||
assertNull(a2.getHostname());
|
||||
assertEquals(0xf1f2, a2.getPort());
|
||||
|
||||
assertEquals(MESSAGE_HEX, HEX.encode(message.bitcoinSerialize()));
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ import org.bitcoinj.params.TestNet3Params;
|
|||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.BufferUnderflowException;
|
||||
import java.nio.ByteBuffer;
|
||||
|
@ -66,11 +67,17 @@ public class BitcoinSerializerTest {
|
|||
assertEquals("10.0.0.1", peerAddress.getAddr().getHostAddress());
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(ADDRESS_MESSAGE_BYTES.length);
|
||||
serializer.serialize(addressMessage, bos);
|
||||
|
||||
assertEquals(31, addressMessage.getMessageSize());
|
||||
addressMessage.addAddress(new PeerAddress(MAINNET, InetAddress.getLocalHost()));
|
||||
|
||||
addressMessage.addAddress(new PeerAddress(MAINNET, InetAddress.getLocalHost(), MAINNET.getPort(),
|
||||
BigInteger.ZERO, serializer.withProtocolVersion(1)));
|
||||
bos = new ByteArrayOutputStream(61);
|
||||
serializer.serialize(addressMessage, bos);
|
||||
assertEquals(61, addressMessage.getMessageSize());
|
||||
|
||||
addressMessage.removeAddress(0);
|
||||
bos = new ByteArrayOutputStream(31);
|
||||
serializer.serialize(addressMessage, bos);
|
||||
assertEquals(31, addressMessage.getMessageSize());
|
||||
|
||||
//this wont be true due to dynamic timestamps.
|
||||
|
|
|
@ -31,11 +31,12 @@ public class PeerAddressTest {
|
|||
private static final NetworkParameters MAINNET = MainNetParams.get();
|
||||
|
||||
@Test
|
||||
public void parse_ancientProtocolVersion() throws Exception {
|
||||
public void parse_versionVariant() throws Exception {
|
||||
MessageSerializer serializer = MAINNET.getDefaultSerializer().withProtocolVersion(0);
|
||||
// copied from https://en.bitcoin.it/wiki/Protocol_documentation#Network_address
|
||||
String hex = "010000000000000000000000000000000000ffff0a000001208d";
|
||||
PeerAddress pa = new PeerAddress(MAINNET, HEX.decode(hex), 0, null,
|
||||
MAINNET.getDefaultSerializer().withProtocolVersion(0));
|
||||
serializer);
|
||||
assertEquals(26, pa.length);
|
||||
assertEquals(VersionMessage.NODE_NETWORK, pa.getServices().longValue());
|
||||
assertEquals("10.0.0.1", pa.getAddr().getHostAddress());
|
||||
|
@ -43,20 +44,22 @@ public class PeerAddressTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void bitcoinSerialize_ancientProtocolVersion() throws Exception {
|
||||
public void bitcoinSerialize_versionVariant() throws Exception {
|
||||
MessageSerializer serializer = MAINNET.getDefaultSerializer().withProtocolVersion(0);
|
||||
PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName(null), 8333, BigInteger.ZERO,
|
||||
MAINNET.getDefaultSerializer().withProtocolVersion(0));
|
||||
assertEquals(26, pa.length);
|
||||
serializer);
|
||||
assertEquals("000000000000000000000000000000000000ffff7f000001208d", Utils.HEX.encode(pa.bitcoinSerialize()));
|
||||
assertEquals(26, pa.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundtrip_ipv4_currentProtocolVersion() throws Exception {
|
||||
public void roundtrip_ipv4_addressV2Variant() throws Exception {
|
||||
long time = Utils.currentTimeSeconds();
|
||||
MessageSerializer serializer = MAINNET.getDefaultSerializer().withProtocolVersion(2);
|
||||
PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("1.2.3.4"), 1234, BigInteger.ZERO,
|
||||
MAINNET.getDefaultSerializer());
|
||||
serializer);
|
||||
byte[] serialized = pa.bitcoinSerialize();
|
||||
PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, null, MAINNET.getDefaultSerializer());
|
||||
PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, null, serializer);
|
||||
assertEquals("1.2.3.4", pa2.getAddr().getHostAddress());
|
||||
assertEquals(1234, pa2.getPort());
|
||||
assertEquals(BigInteger.ZERO, pa2.getServices());
|
||||
|
@ -64,12 +67,26 @@ public class PeerAddressTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void roundtrip_ipv4_ancientProtocolVersion() throws Exception {
|
||||
public void roundtrip_ipv4_addressVariant() throws Exception {
|
||||
long time = Utils.currentTimeSeconds();
|
||||
MessageSerializer serializer = MAINNET.getDefaultSerializer().withProtocolVersion(1);
|
||||
PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("1.2.3.4"), 1234, BigInteger.ZERO,
|
||||
MAINNET.getDefaultSerializer().withProtocolVersion(0));
|
||||
serializer);
|
||||
byte[] serialized = pa.bitcoinSerialize();
|
||||
PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, null,
|
||||
MAINNET.getDefaultSerializer().withProtocolVersion(0));
|
||||
PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, null, serializer);
|
||||
assertEquals("1.2.3.4", pa2.getAddr().getHostAddress());
|
||||
assertEquals(1234, pa2.getPort());
|
||||
assertEquals(BigInteger.ZERO, pa2.getServices());
|
||||
assertTrue(pa2.getTime() >= time && pa2.getTime() < time + 5); // potentially racy
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundtrip_ipv4_versionVariant() throws Exception {
|
||||
MessageSerializer serializer = MAINNET.getDefaultSerializer().withProtocolVersion(0);
|
||||
PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("1.2.3.4"), 1234, BigInteger.ZERO,
|
||||
serializer);
|
||||
byte[] serialized = pa.bitcoinSerialize();
|
||||
PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, null, serializer);
|
||||
assertEquals("1.2.3.4", pa2.getAddr().getHostAddress());
|
||||
assertEquals(1234, pa2.getPort());
|
||||
assertEquals(BigInteger.ZERO, pa2.getServices());
|
||||
|
@ -77,12 +94,13 @@ public class PeerAddressTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void roundtrip_ipv6_currentProtocolVersion() throws Exception {
|
||||
public void roundtrip_ipv6_addressV2Variant() throws Exception {
|
||||
long time = Utils.currentTimeSeconds();
|
||||
MessageSerializer serializer = MAINNET.getDefaultSerializer().withProtocolVersion(2);
|
||||
PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7334"), 1234,
|
||||
BigInteger.ZERO, MAINNET.getDefaultSerializer());
|
||||
BigInteger.ZERO, serializer);
|
||||
byte[] serialized = pa.bitcoinSerialize();
|
||||
PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, null, MAINNET.getDefaultSerializer());
|
||||
PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, null, serializer);
|
||||
assertEquals("2001:db8:85a3:0:0:8a2e:370:7334", pa2.getAddr().getHostAddress());
|
||||
assertEquals(1234, pa2.getPort());
|
||||
assertEquals(BigInteger.ZERO, pa2.getServices());
|
||||
|
@ -90,12 +108,27 @@ public class PeerAddressTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void roundtrip_ipv6_ancientProtocolVersion() throws Exception {
|
||||
public void roundtrip_ipv6_addressVariant() throws Exception {
|
||||
long time = Utils.currentTimeSeconds();
|
||||
MessageSerializer serializer = MAINNET.getDefaultSerializer().withProtocolVersion(1);
|
||||
PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7334"), 1234,
|
||||
BigInteger.ZERO, MAINNET.getDefaultSerializer().withProtocolVersion(0));
|
||||
BigInteger.ZERO, serializer);
|
||||
byte[] serialized = pa.bitcoinSerialize();
|
||||
PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, null, serializer);
|
||||
assertEquals("2001:db8:85a3:0:0:8a2e:370:7334", pa2.getAddr().getHostAddress());
|
||||
assertEquals(1234, pa2.getPort());
|
||||
assertEquals(BigInteger.ZERO, pa2.getServices());
|
||||
assertTrue(pa2.getTime() >= time && pa2.getTime() < time + 5); // potentially racy
|
||||
}
|
||||
|
||||
@Test
|
||||
public void roundtrip_ipv6_versionVariant() throws Exception {
|
||||
MessageSerializer serializer = MAINNET.getDefaultSerializer().withProtocolVersion(0);
|
||||
PeerAddress pa = new PeerAddress(MAINNET, InetAddress.getByName("2001:db8:85a3:0:0:8a2e:370:7334"), 1234,
|
||||
BigInteger.ZERO, serializer);
|
||||
byte[] serialized = pa.bitcoinSerialize();
|
||||
PeerAddress pa2 = new PeerAddress(MAINNET, serialized, 0, null,
|
||||
MAINNET.getDefaultSerializer().withProtocolVersion(0));
|
||||
serializer);
|
||||
assertEquals("2001:db8:85a3:0:0:8a2e:370:7334", pa2.getAddr().getHostAddress());
|
||||
assertEquals(1234, pa2.getPort());
|
||||
assertEquals(BigInteger.ZERO, pa2.getServices());
|
||||
|
|
|
@ -158,6 +158,7 @@ public class TestWithPeerGroup extends TestWithNetworkConnections {
|
|||
|
||||
private void stepThroughInit(VersionMessage versionMessage, InboundMessageQueuer writeTarget) throws InterruptedException {
|
||||
checkState(writeTarget.nextMessageBlocking() instanceof VersionMessage);
|
||||
checkState(writeTarget.nextMessageBlocking() instanceof SendAddrV2Message);
|
||||
checkState(writeTarget.nextMessageBlocking() instanceof VersionAck);
|
||||
if (versionMessage.isBloomFilteringSupported()) {
|
||||
checkState(writeTarget.nextMessageBlocking() instanceof BloomFilter);
|
||||
|
|
Loading…
Add table
Reference in a new issue