PeerGroup: Require SegWit protocol and service when selecting a download peer.

Those nodes are extremely common now.
This commit is contained in:
Andreas Schildbach 2020-02-27 20:51:01 +01:00
parent 8d983649d3
commit 95e08ef86c
3 changed files with 23 additions and 29 deletions

View file

@ -2208,37 +2208,29 @@ public class PeerGroup implements TransactionBroadcaster {
// Make sure we don't select a peer if there is no consensus about block height.
if (mostCommonChainHeight == 0)
return null;
// Make sure we don't select a peer that is behind/synchronizing itself or announces an unrealistic height.
List<Peer> candidates = new ArrayList<>();
// Only select peers that announce the minimum protocol and services and that we think is fully synchronized.
List<Peer> candidates = new LinkedList<>();
final int MINIMUM_VERSION = params.getProtocolVersionNum(NetworkParameters.ProtocolVersion.WITNESS_VERSION);
for (Peer peer : peers) {
if (!peer.getPeerVersionMessage().hasBlockChain())
final VersionMessage versionMessage = peer.getPeerVersionMessage();
if (versionMessage.clientVersion < MINIMUM_VERSION)
continue;
if (!versionMessage.hasBlockChain())
continue;
if (!versionMessage.isWitnessSupported())
continue;
final long peerHeight = peer.getBestHeight();
if (peerHeight < mostCommonChainHeight || peerHeight > mostCommonChainHeight + 1)
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
// zap peers if they upgrade early. If we can't find any peers that have our preferred protocol version or
// better then we'll settle for the highest we found instead.
int highestVersion = 0, preferredVersion = 0;
// If/when PREFERRED_VERSION is not equal to vMinRequiredProtocolVersion, reenable the last test in PeerGroupTest.downloadPeerSelection
final int PREFERRED_VERSION = params.getProtocolVersionNum(NetworkParameters.ProtocolVersion.BLOOM_FILTER);
for (Peer peer : candidates) {
highestVersion = Math.max(peer.getPeerVersionMessage().clientVersion, highestVersion);
preferredVersion = Math.min(highestVersion, PREFERRED_VERSION);
}
ArrayList<Peer> candidates2 = new ArrayList<>(candidates.size());
for (Peer peer : candidates) {
if (peer.getPeerVersionMessage().clientVersion >= preferredVersion) {
candidates2.add(peer);
}
}
if (candidates2.isEmpty())
if (candidates.isEmpty())
return null;
int index = (int) (Math.random() * candidates2.size());
return candidates2.get(index);
// Random poll.
int index = (int) (Math.random() * candidates.size());
return candidates.get(index);
}
/**

View file

@ -469,11 +469,11 @@ public class PeerGroupTest extends TestWithPeerGroup {
public void downloadPeerSelection() throws Exception {
peerGroup.start();
VersionMessage v1 = new VersionMessage(UNITTEST, 2);
v1.clientVersion = NetworkParameters.ProtocolVersion.BLOOM_FILTER.getBitcoinProtocolVersion();
v1.localServices = VersionMessage.NODE_NETWORK;
v1.clientVersion = NetworkParameters.ProtocolVersion.WITNESS_VERSION.getBitcoinProtocolVersion();
v1.localServices = VersionMessage.NODE_NETWORK | VersionMessage.NODE_BLOOM | VersionMessage.NODE_WITNESS;
VersionMessage v2 = new VersionMessage(UNITTEST, 4);
v2.clientVersion = NetworkParameters.ProtocolVersion.BLOOM_FILTER.getBitcoinProtocolVersion();
v2.localServices = VersionMessage.NODE_NETWORK;
v2.clientVersion = NetworkParameters.ProtocolVersion.WITNESS_VERSION.getBitcoinProtocolVersion();
v2.localServices = VersionMessage.NODE_NETWORK | VersionMessage.NODE_BLOOM | VersionMessage.NODE_WITNESS;
assertNull(peerGroup.getDownloadPeer());
Peer p1 = connectPeer(0, v1).peer;

View file

@ -61,8 +61,10 @@ public class TestWithPeerGroup extends TestWithNetworkConnections {
super.setUp(blockStore);
remoteVersionMessage = new VersionMessage(UNITTEST, 1);
remoteVersionMessage.localServices = VersionMessage.NODE_NETWORK;
remoteVersionMessage.clientVersion = NotFoundMessage.MIN_PROTOCOL_VERSION;
remoteVersionMessage.localServices =
VersionMessage.NODE_NETWORK | VersionMessage.NODE_BLOOM | VersionMessage.NODE_WITNESS;
remoteVersionMessage.clientVersion =
NetworkParameters.ProtocolVersion.WITNESS_VERSION.getBitcoinProtocolVersion();
blockJobs = false;
initPeerGroup();
}