3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-30 23:02:15 +00:00

Add a minimum version to Peer and use it to exclude peers so old they don't support pong messages.

This commit is contained in:
Mike Hearn 2013-02-05 15:14:58 +01:00
parent f488c29c12
commit 5ce607f1ae
2 changed files with 52 additions and 4 deletions

View File

@ -89,7 +89,8 @@ public class Peer {
// It is important to avoid a nasty edge case where we can end up with parallel chain downloads proceeding
// simultaneously if we were to receive a newly solved block whilst parts of the chain are streaming to us.
private HashSet<Sha256Hash> pendingBlockDownloads = new HashSet<Sha256Hash>();
// The lowest version number we're willing to accept. Lower than this will result in an immediate disconnect.
private int minProtocolVersion = Pong.MIN_PROTOCOL_VERSION;
// When an API user explicitly requests a block or transaction from a peer, the InventoryItem is put here
// whilst waiting for the response. Synchronized on itself. Is not used for downloads Peer generates itself.
private static class GetDataRequest {
@ -279,6 +280,11 @@ public class Peer {
listener.onPeerConnected(Peer.this);
}
});
if (peerVersionMessage.clientVersion < minProtocolVersion) {
log.warn("Connected to a peer speaking protocol version {} but need {}, closing",
peerVersionMessage.clientVersion, minProtocolVersion);
e.getChannel().close();
}
} else if (m instanceof VersionAck) {
synchronized (Peer.this) {
if (peerVersionMessage == null) {
@ -295,7 +301,6 @@ public class Peer {
} else if (m instanceof Pong) {
processPong((Pong)m);
} else {
// TODO: Handle the other messages we can receive.
log.warn("Received unhandled message: {}", m);
}
}
@ -1203,4 +1208,21 @@ public class Peer {
public synchronized long getBestHeight() {
return peerVersionMessage.bestHeight + blocksAnnounced;
}
/**
* The minimum P2P protocol version that is accepted. If the peer speaks a protocol version lower than this, it
* will be disconnected.
* @return if not-null then this is the future for the Peer disconnection event.
*/
public ChannelFuture setMinProtocolVersion(int minProtocolVersion) {
synchronized (this) {
this.minProtocolVersion = minProtocolVersion;
}
if (getVersionMessage().clientVersion < minProtocolVersion) {
log.warn("{}: Disconnecting due to new min protocol version {}", this, minProtocolVersion);
return Channels.close(channel);
} else {
return null;
}
}
}

View File

@ -630,8 +630,7 @@ public class PeerTest extends TestWithNetworkConnections {
t2.setLockTime(999999);
// Add a fake input to t3 that goes nowhere.
Sha256Hash t3 = Sha256Hash.create("abc".getBytes(Charset.forName("UTF-8")));
t2.addInput(new TransactionInput(unitTestParams, t2, new byte[]{}, new TransactionOutPoint(unitTestParams, 0,
t3)));
t2.addInput(new TransactionInput(unitTestParams, t2, new byte[]{}, new TransactionOutPoint(unitTestParams, 0, t3)));
t2.addOutput(Utils.toNanoCoins(1, 0), new ECKey());
Transaction t1 = new Transaction(unitTestParams);
t1.addInput(t2.getOutput(0));
@ -664,6 +663,33 @@ public class PeerTest extends TestWithNetworkConnections {
assertNull(vtx[0]);
}
@Test
public void disconnectOldVersions1() throws Exception {
expect(channel.close()).andReturn(null);
control.replay();
// Set up the connection with an old version.
handler.connectRequested(ctx, new UpstreamChannelStateEvent(channel, ChannelState.CONNECTED, socketAddress));
VersionMessage peerVersion = new VersionMessage(unitTestParams, OTHER_PEER_CHAIN_HEIGHT);
peerVersion.clientVersion = 500;
DownstreamMessageEvent versionEvent =
new DownstreamMessageEvent(channel, Channels.future(channel), peerVersion, null);
handler.messageReceived(ctx, versionEvent);
}
@Test
public void disconnectOldVersions2() throws Exception {
expect(channel.close()).andReturn(null);
control.replay();
// Set up the connection with an old version.
handler.connectRequested(ctx, new UpstreamChannelStateEvent(channel, ChannelState.CONNECTED, socketAddress));
VersionMessage peerVersion = new VersionMessage(unitTestParams, OTHER_PEER_CHAIN_HEIGHT);
peerVersion.clientVersion = 70000;
DownstreamMessageEvent versionEvent =
new DownstreamMessageEvent(channel, Channels.future(channel), peerVersion, null);
handler.messageReceived(ctx, versionEvent);
peer.setMinProtocolVersion(500);
}
// TODO: Use generics here to avoid unnecessary casting.
private Message outbound() {
List<DownstreamMessageEvent> messages = event.getValues();