3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-12 10:15:52 +00:00

Peer: Also connect to peers which serve only the last two days worth of blocks, but download only from those that have the full blockchain.

This implements BIP159.
This commit is contained in:
Andreas Schildbach 2019-01-31 12:46:10 +01:00
parent 0c2a9e646c
commit 2254bd9777
3 changed files with 27 additions and 12 deletions

View File

@ -432,6 +432,10 @@ public class Peer extends PeerSocketHandler {
a.add("WITNESS");
services &= ~VersionMessage.NODE_WITNESS;
}
if ((services & VersionMessage.NODE_NETWORK_LIMITED) == VersionMessage.NODE_NETWORK_LIMITED) {
a.add("NETWORK_LIMITED");
services &= ~VersionMessage.NODE_NETWORK_LIMITED;
}
if (services != 0)
a.add("remaining: " + Long.toBinaryString(services));
return Joiner.on(", ").join(a);
@ -581,10 +585,10 @@ public class Peer extends PeerSocketHandler {
// mode nodes because we can't download the data from them we need to find/verify transactions. Some bogus
// implementations claim to have a block chain in their services field but then report a height of zero, filter
// them out here.
if (!vPeerVersionMessage.hasBlockChain() ||
if (!vPeerVersionMessage.hasLimitedBlockChain() ||
(!params.allowEmptyPeerChain() && vPeerVersionMessage.bestHeight == 0)) {
// Shut down the channel gracefully.
log.info("{}: Peer does not have a copy of the block chain.", this);
log.info("{}: Peer does not have at least a recent part of the block chain.", this);
close();
return;
}

View File

@ -2188,7 +2188,11 @@ public class PeerGroup implements TransactionBroadcaster {
int mostCommonChainHeight = getMostCommonChainHeight(peers);
List<Peer> candidates = new ArrayList<>();
for (Peer peer : peers) {
if (peer.getBestHeight() == mostCommonChainHeight) candidates.add(peer);
if (!peer.getPeerVersionMessage().hasBlockChain())
continue;
if (peer.getBestHeight() < mostCommonChainHeight)
continue;
candidates.add(peer);
}
// Of the candidates, find the peers that meet the minimum protocol version we want to target. We could select
// the highest version we've seen on the assumption that newer versions are always better but we don't want to

View File

@ -45,12 +45,14 @@ public class VersionMessage extends Message {
/** The value that is prepended to the subVer field of this application. */
public static final String LIBRARY_SUBVER = "/bitcoinj:" + BITCOINJ_VERSION + "/";
/** A service bit that denotes whether the peer has a copy of the block chain or not. */
/** A service bit that denotes whether the peer has a full copy of the block chain or not. */
public static final int NODE_NETWORK = 1 << 0;
/** A service bit that denotes whether the peer supports the getutxos message or not. */
public static final int NODE_GETUTXOS = 1 << 1;
/** Indicates that a node can be asked for blocks and transactions including witness data. */
public static final int NODE_WITNESS = 1 << 3;
/** A service bit that denotes whether the peer has at least the last two days worth of blockchain (BIP159). */
public static final int NODE_NETWORK_LIMITED = 1 << 10;
/** A service bit used by Bitcoin-ABC to announce Bitcoin Cash nodes. */
public static final int NODE_BITCOIN_CASH = 1 << 5;
@ -178,14 +180,6 @@ public class VersionMessage extends Message {
}
}
/**
* Returns true if the version message indicates the sender has a full copy of the block chain,
* or if it's running in client mode (only has the headers).
*/
public boolean hasBlockChain() {
return (localServices & NODE_NETWORK) == NODE_NETWORK;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@ -297,4 +291,17 @@ public class VersionMessage extends Message {
public boolean isWitnessSupported() {
return (localServices & NODE_WITNESS) == NODE_WITNESS;
}
/**
* Returns true if the version message indicates the sender has a full copy of the block chain, or false if it's
* running in client mode (only has the headers).
*/
public boolean hasBlockChain() {
return (localServices & NODE_NETWORK) == NODE_NETWORK;
}
/** Returns true if the peer has at least the last two days worth of blockchain (BIP159). */
public boolean hasLimitedBlockChain() {
return hasBlockChain() || (localServices & NODE_NETWORK_LIMITED) == NODE_NETWORK_LIMITED;
}
}