|
|
@ -55,7 +55,9 @@ import java.util.Collections; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.Optional; |
|
|
|
import java.util.Optional; |
|
|
|
|
|
|
|
import java.util.concurrent.CompletableFuture; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
import java.util.concurrent.TimeUnit; |
|
|
|
|
|
|
|
import java.util.concurrent.TimeoutException; |
|
|
|
import java.util.concurrent.atomic.AtomicInteger; |
|
|
|
import java.util.concurrent.atomic.AtomicInteger; |
|
|
|
import java.util.function.Consumer; |
|
|
|
import java.util.function.Consumer; |
|
|
|
import java.util.stream.Collectors; |
|
|
|
import java.util.stream.Collectors; |
|
|
@ -468,14 +470,13 @@ public class PeerDiscoveryControllerTest { |
|
|
|
.build(); |
|
|
|
.build(); |
|
|
|
|
|
|
|
|
|
|
|
// Mock the creation of the PING packet, so that we can control the hash, which gets validated
|
|
|
|
// Mock the creation of the PING packet, so that we can control the hash, which gets validated
|
|
|
|
// when
|
|
|
|
// when processing the PONG.
|
|
|
|
// processing the PONG.
|
|
|
|
|
|
|
|
final PingPacketData mockPing = |
|
|
|
final PingPacketData mockPing = |
|
|
|
PingPacketData.create( |
|
|
|
PingPacketData.create( |
|
|
|
Optional.ofNullable(localPeer.getEndpoint()), peers.get(0).getEndpoint(), UInt64.ONE); |
|
|
|
Optional.ofNullable(localPeer.getEndpoint()), peers.get(0).getEndpoint(), UInt64.ONE); |
|
|
|
final Packet mockPacket = Packet.create(PacketType.PING, mockPing, nodeKeys.get(0)); |
|
|
|
final Packet mockPacket = Packet.create(PacketType.PING, mockPing, nodeKeys.get(0)); |
|
|
|
mockPingPacketCreation(mockPacket); |
|
|
|
mockPingPacketCreation(mockPacket); |
|
|
|
controller.setRetryDelayFunction((prev) -> 999999999L); |
|
|
|
controller.setRetryDelayFunction(PeerDiscoveryControllerTest::longDelayFunction); |
|
|
|
controller.start(); |
|
|
|
controller.start(); |
|
|
|
|
|
|
|
|
|
|
|
// Verify that the PING was sent.
|
|
|
|
// Verify that the PING was sent.
|
|
|
@ -506,11 +507,68 @@ public class PeerDiscoveryControllerTest { |
|
|
|
.isEqualTo(PeerDiscoveryStatus.BONDED); |
|
|
|
.isEqualTo(PeerDiscoveryStatus.BONDED); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Test |
|
|
|
|
|
|
|
public void addedToInvalidIpsWhenConnectTimedOut() { |
|
|
|
|
|
|
|
// Create a peer
|
|
|
|
|
|
|
|
final List<NodeKey> nodeKeys = PeerDiscoveryTestHelper.generateNodeKeys(1); |
|
|
|
|
|
|
|
final NodeKey nodeKey = nodeKeys.getFirst(); |
|
|
|
|
|
|
|
final DiscoveryPeer peerThatTimesOut = helper.createDiscoveryPeers(nodeKeys).getFirst(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Initialize the peer controller, using a rlpx agent that times out when asked to connect.
|
|
|
|
|
|
|
|
// Set a high controller refresh interval and a high timeout threshold, to avoid retries
|
|
|
|
|
|
|
|
// getting in the way of this test.
|
|
|
|
|
|
|
|
final OutboundMessageHandler outboundMessageHandler = mock(OutboundMessageHandler.class); |
|
|
|
|
|
|
|
RlpxAgent rlpxAgentMock = mock(RlpxAgent.class); |
|
|
|
|
|
|
|
when(rlpxAgentMock.connect(any())) |
|
|
|
|
|
|
|
.thenReturn(CompletableFuture.failedFuture(new Exception(new TimeoutException()))); |
|
|
|
|
|
|
|
controller = |
|
|
|
|
|
|
|
getControllerBuilder() |
|
|
|
|
|
|
|
.outboundMessageHandler(outboundMessageHandler) |
|
|
|
|
|
|
|
.rlpxAgent(rlpxAgentMock) |
|
|
|
|
|
|
|
.build(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Mock the creation of the PING packet, so that we can control the hash, which gets validated
|
|
|
|
|
|
|
|
// when processing the PONG.
|
|
|
|
|
|
|
|
final PingPacketData mockPing = |
|
|
|
|
|
|
|
PingPacketData.create( |
|
|
|
|
|
|
|
Optional.ofNullable(localPeer.getEndpoint()), |
|
|
|
|
|
|
|
peerThatTimesOut.getEndpoint(), |
|
|
|
|
|
|
|
UInt64.ONE); |
|
|
|
|
|
|
|
final Packet mockPacket = Packet.create(PacketType.PING, mockPing, nodeKey); |
|
|
|
|
|
|
|
mockPingPacketCreation(mockPacket); |
|
|
|
|
|
|
|
controller.setRetryDelayFunction(PeerDiscoveryControllerTest::longDelayFunction); |
|
|
|
|
|
|
|
controller.start(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
controller.handleBondingRequest(peerThatTimesOut); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Verify that the PING was sent.
|
|
|
|
|
|
|
|
verify(outboundMessageHandler, times(1)) |
|
|
|
|
|
|
|
.send(eq(peerThatTimesOut), matchPacketOfType(PacketType.PING)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Simulate a PONG message from the peer.
|
|
|
|
|
|
|
|
respondWithPong(peerThatTimesOut, nodeKey, mockPacket.getHash()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
final List<DiscoveryPeer> peersInTable = controller.streamDiscoveredPeers().toList(); |
|
|
|
|
|
|
|
assertThat(peersInTable).hasSize(0); |
|
|
|
|
|
|
|
assertThat(peersInTable).doesNotContain(peerThatTimesOut); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Try bonding again, and check that the peer is not sent the PING packet again
|
|
|
|
|
|
|
|
controller.handleBondingRequest(peerThatTimesOut); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// verify that the ping was not sent, no additional interaction
|
|
|
|
|
|
|
|
verify(outboundMessageHandler, times(1)) |
|
|
|
|
|
|
|
.send(eq(peerThatTimesOut), matchPacketOfType(PacketType.PING)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private ControllerBuilder getControllerBuilder() { |
|
|
|
private ControllerBuilder getControllerBuilder() { |
|
|
|
|
|
|
|
final RlpxAgent rlpxAgent = mock(RlpxAgent.class); |
|
|
|
|
|
|
|
when(rlpxAgent.connect(any())) |
|
|
|
|
|
|
|
.thenReturn(CompletableFuture.failedFuture(new RuntimeException())); |
|
|
|
return ControllerBuilder.create() |
|
|
|
return ControllerBuilder.create() |
|
|
|
.nodeKey(localNodeKey) |
|
|
|
.nodeKey(localNodeKey) |
|
|
|
.localPeer(localPeer) |
|
|
|
.localPeer(localPeer) |
|
|
|
.peerTable(peerTable); |
|
|
|
.peerTable(peerTable) |
|
|
|
|
|
|
|
.rlpxAgent(rlpxAgent); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void respondWithPong( |
|
|
|
private void respondWithPong( |
|
|
@ -544,7 +602,7 @@ public class PeerDiscoveryControllerTest { |
|
|
|
|
|
|
|
|
|
|
|
mockPingPacketCreation(pingPacket); |
|
|
|
mockPingPacketCreation(pingPacket); |
|
|
|
|
|
|
|
|
|
|
|
controller.setRetryDelayFunction((prev) -> 999999999L); |
|
|
|
controller.setRetryDelayFunction(PeerDiscoveryControllerTest::longDelayFunction); |
|
|
|
controller.start(); |
|
|
|
controller.start(); |
|
|
|
|
|
|
|
|
|
|
|
verify(outboundMessageHandler, times(1)) |
|
|
|
verify(outboundMessageHandler, times(1)) |
|
|
@ -994,7 +1052,7 @@ public class PeerDiscoveryControllerTest { |
|
|
|
.build(); |
|
|
|
.build(); |
|
|
|
mockPingPacketCreation(pingPacket); |
|
|
|
mockPingPacketCreation(pingPacket); |
|
|
|
|
|
|
|
|
|
|
|
controller.setRetryDelayFunction((prev) -> 999999999L); |
|
|
|
controller.setRetryDelayFunction(PeerDiscoveryControllerTest::longDelayFunction); |
|
|
|
controller.start(); |
|
|
|
controller.start(); |
|
|
|
|
|
|
|
|
|
|
|
verify(outboundMessageHandler, times(1)).send(any(), matchPacketOfType(PacketType.PING)); |
|
|
|
verify(outboundMessageHandler, times(1)).send(any(), matchPacketOfType(PacketType.PING)); |
|
|
@ -1689,6 +1747,7 @@ public class PeerDiscoveryControllerTest { |
|
|
|
private Cache<Bytes, Packet> enrs = |
|
|
|
private Cache<Bytes, Packet> enrs = |
|
|
|
CacheBuilder.newBuilder().maximumSize(50).expireAfterWrite(10, TimeUnit.SECONDS).build(); |
|
|
|
CacheBuilder.newBuilder().maximumSize(50).expireAfterWrite(10, TimeUnit.SECONDS).build(); |
|
|
|
private boolean filterOnForkId = false; |
|
|
|
private boolean filterOnForkId = false; |
|
|
|
|
|
|
|
private RlpxAgent rlpxAgent; |
|
|
|
|
|
|
|
|
|
|
|
public static ControllerBuilder create() { |
|
|
|
public static ControllerBuilder create() { |
|
|
|
return new ControllerBuilder(); |
|
|
|
return new ControllerBuilder(); |
|
|
@ -1744,6 +1803,11 @@ public class PeerDiscoveryControllerTest { |
|
|
|
return this; |
|
|
|
return this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public ControllerBuilder rlpxAgent(final RlpxAgent rlpxAgent) { |
|
|
|
|
|
|
|
this.rlpxAgent = rlpxAgent; |
|
|
|
|
|
|
|
return this; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
PeerDiscoveryController build() { |
|
|
|
PeerDiscoveryController build() { |
|
|
|
checkNotNull(nodeKey); |
|
|
|
checkNotNull(nodeKey); |
|
|
|
if (localPeer == null) { |
|
|
|
if (localPeer == null) { |
|
|
@ -1752,6 +1816,7 @@ public class PeerDiscoveryControllerTest { |
|
|
|
if (peerTable == null) { |
|
|
|
if (peerTable == null) { |
|
|
|
peerTable = new PeerTable(localPeer.getId()); |
|
|
|
peerTable = new PeerTable(localPeer.getId()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return spy( |
|
|
|
return spy( |
|
|
|
PeerDiscoveryController.builder() |
|
|
|
PeerDiscoveryController.builder() |
|
|
|
.nodeKey(nodeKey) |
|
|
|
.nodeKey(nodeKey) |
|
|
@ -1767,7 +1832,7 @@ public class PeerDiscoveryControllerTest { |
|
|
|
.metricsSystem(new NoOpMetricsSystem()) |
|
|
|
.metricsSystem(new NoOpMetricsSystem()) |
|
|
|
.cacheForEnrRequests(enrs) |
|
|
|
.cacheForEnrRequests(enrs) |
|
|
|
.filterOnEnrForkId(filterOnForkId) |
|
|
|
.filterOnEnrForkId(filterOnForkId) |
|
|
|
.rlpxAgent(mock(RlpxAgent.class)) |
|
|
|
.rlpxAgent(rlpxAgent) |
|
|
|
.build()); |
|
|
|
.build()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|