Ensure devp2p ports are written to ports file correctly (#1020)

Start P2P network synchronously so the ports are guaranteed to be known before we write the ports file
Include the P2P TCP port in ports file even when peer discovery is disabled.
Load information from the advertised peer rather than the discovery listening socket.
Fix admin_nodeInfo to include the ?discport param in the enode URI when the discovery port differs from the P2P port.
Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Adrian Sutton 6 years ago committed by GitHub
parent ae09385641
commit ae528fc7cb
  1. 2
      ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNodeList.java
  2. 37
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminNodeInfo.java
  3. 24
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminNodeInfoTest.java
  4. 8
      ethereum/mock-p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/testing/MockNetwork.java
  5. 13
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/NetworkRunner.java
  6. 8
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/NoopP2PNetwork.java
  7. 11
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/api/P2PNetwork.java
  8. 12
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgent.java
  9. 4
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryController.java
  10. 20
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/netty/NettyP2PNetwork.java
  11. 4
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/peers/Peer.java
  12. 26
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/NettyP2PNetworkTest.java
  13. 37
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/NetworkingServiceLifecycleTest.java
  14. 8
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgentTest.java
  15. 5
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBondingTest.java
  16. 22
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryBootstrappingTest.java
  17. 5
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryObserversTest.java
  18. 3
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTestHelper.java
  19. 4
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTimestampsTest.java
  20. 2
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPeerDiscoveryAgent.java
  21. 20
      pantheon/src/main/java/tech/pegasys/pantheon/Runner.java
  22. 18
      pantheon/src/test/java/tech/pegasys/pantheon/RunnerTest.java
  23. 5
      util/src/main/java/tech/pegasys/pantheon/util/bytes/BytesValue.java

@ -61,7 +61,7 @@ public class TestNodeList implements Closeable {
public void startNetworks() {
for (final TestNode node : nodes) {
node.network.run();
node.network.start();
}
}

@ -22,15 +22,13 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.p2p.P2pDisabledException;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Map;
import com.google.common.collect.ImmutableMap;
import com.google.common.net.InetAddresses;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -67,25 +65,26 @@ public class AdminNodeInfo implements JsonRpcMethod {
try {
final Map<String, Object> response = new HashMap<>();
final BytesValue nodeId = peerNetwork.getLocalPeerInfo().getNodeId();
final InetSocketAddress address = peerNetwork.getDiscoverySocketAddress();
final int port = peerNetwork.getLocalPeerInfo().getPort();
final Map<String, Integer> ports = new HashMap<>();
final InetAddress inetAddress = address.getAddress();
response.put(
"enode",
"enode://"
+ nodeId.toString().substring(2)
+ "@"
+ InetAddresses.toUriString(inetAddress)
+ ":"
+ port);
final PeerInfo peerInfo = peerNetwork.getLocalPeerInfo();
final BytesValue nodeId = peerInfo.getNodeId();
peerNetwork
.getAdvertisedPeer()
.ifPresent(
advertisedPeer -> {
response.put("enode", advertisedPeer.getEnodeURI());
ports.put("discovery", advertisedPeer.getEndpoint().getUdpPort());
response.put("ip", advertisedPeer.getEndpoint().getHost());
response.put(
"listenAddr",
advertisedPeer.getEndpoint().getHost() + ":" + peerInfo.getPort());
});
response.put("id", nodeId.toString().substring(2));
// this doesn't provide a useful value yet.
// response.put("ip", inetAddress.getHostAddress());
response.put("listenAddr", InetAddresses.toUriString(inetAddress) + ":" + port);
response.put("name", clientVersion);
response.put("ports", ImmutableMap.of("discovery", port, "listener", port /*??*/));
ports.put("listener", peerInfo.getPort());
response.put("ports", ports);
final ChainHead chainHead = blockchainQueries.getBlockchain().getChainHead();
response.put(

@ -14,6 +14,7 @@ package tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.config.GenesisConfigOptions;
@ -25,11 +26,11 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.queries.BlockchainQueries;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer;
import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256;
import java.net.InetSocketAddress;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -51,17 +52,19 @@ public class AdminNodeInfoTest {
private AdminNodeInfo method;
private final PeerInfo localPeer =
new PeerInfo(5, "0x0", Collections.emptyList(), 30303, BytesValue.EMPTY);
private final InetSocketAddress discoverySocketAddress = new InetSocketAddress("1.2.3.4", 7890);
private final BytesValue nodeId =
BytesValue.fromHexString(
"0x0f1b319e32017c3fcb221841f0f978701b4e9513fe6a567a2db43d43381a9c7e3dfe7cae13cbc2f56943400bacaf9082576ab087cd51983b17d729ae796f6807");
private final PeerInfo localPeer = new PeerInfo(5, "0x0", Collections.emptyList(), 30303, nodeId);
private final ChainHead testChainHead = new ChainHead(Hash.EMPTY, UInt256.ONE);
private final GenesisConfigOptions genesisConfigOptions =
new StubGenesisConfigOptions().chainId(2019);
private final DefaultPeer defaultPeer = new DefaultPeer(nodeId, "1.2.3.4", 7890, 30303);
@Before
public void setup() {
when(p2pNetwork.getLocalPeerInfo()).thenReturn(localPeer);
when(p2pNetwork.getDiscoverySocketAddress()).thenReturn(discoverySocketAddress);
doReturn(Optional.of(this.defaultPeer)).when(p2pNetwork).getAdvertisedPeer();
when(blockchainQueries.getBlockchain()).thenReturn(blockchain);
when(blockchainQueries.getBlockHashByNumber(anyLong())).thenReturn(Optional.of(Hash.EMPTY));
when(blockchain.getChainHead()).thenReturn(testChainHead);
@ -77,11 +80,16 @@ public class AdminNodeInfoTest {
final JsonRpcSuccessResponse actual = (JsonRpcSuccessResponse) method.response(request);
final Map<String, Object> expected = new HashMap<>();
expected.put("enode", "enode://@1.2.3.4:30303");
expected.put("id", "");
expected.put(
"enode",
"enode://0f1b319e32017c3fcb221841f0f978701b4e9513fe6a567a2db43d43381a9c7e3dfe7cae13cbc2f56943400bacaf9082576ab087cd51983b17d729ae796f6807@1.2.3.4:30303?discport=7890");
expected.put(
"id",
"0f1b319e32017c3fcb221841f0f978701b4e9513fe6a567a2db43d43381a9c7e3dfe7cae13cbc2f56943400bacaf9082576ab087cd51983b17d729ae796f6807");
expected.put("ip", "1.2.3.4");
expected.put("listenAddr", "1.2.3.4:30303");
expected.put("name", "testnet/1.0/this/that");
expected.put("ports", ImmutableMap.of("discovery", 30303, "listener", 30303));
expected.put("ports", ImmutableMap.of("discovery", 7890, "listener", 30303));
expected.put(
"protocols",
ImmutableMap.of(

@ -17,6 +17,7 @@ import tech.pegasys.pantheon.ethereum.p2p.api.Message;
import tech.pegasys.pantheon.ethereum.p2p.api.MessageData;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.api.PeerConnection;
import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.wire.Capability;
import tech.pegasys.pantheon.ethereum.p2p.wire.DefaultMessage;
@ -25,7 +26,6 @@ import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.Discon
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.util.Subscribers;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collection;
@ -177,12 +177,12 @@ public final class MockNetwork {
public void awaitStop() {}
@Override
public InetSocketAddress getDiscoverySocketAddress() {
return null;
public Optional<Peer> getAdvertisedPeer() {
return Optional.of(new DefaultPeer(self.getId(), "127.0.0.1", 0, 0));
}
@Override
public void run() {}
public void start() {}
@Override
public void close() {}

@ -29,7 +29,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@ -37,7 +36,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
import java.util.stream.Collectors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -48,9 +46,6 @@ public class NetworkRunner implements AutoCloseable {
private final AtomicBoolean started = new AtomicBoolean(false);
private final AtomicBoolean stopped = new AtomicBoolean(false);
private final ExecutorService networkExecutor =
Executors.newFixedThreadPool(
1, new ThreadFactoryBuilder().setNameFormat(this.getClass().getSimpleName()).build());
private final ScheduledExecutorService networkCheckExecutor =
Executors.newSingleThreadScheduledExecutor();
@ -89,7 +84,7 @@ public class NetworkRunner implements AutoCloseable {
if (started.compareAndSet(false, true)) {
LOG.info("Starting Network.");
setupHandlers();
networkExecutor.submit(network);
network.start();
networkCheckExecutor.scheduleWithFixedDelay(
network::checkMaintainedConnectionPeers, 60, 60, TimeUnit.SECONDS);
} else {
@ -104,7 +99,6 @@ public class NetworkRunner implements AutoCloseable {
for (final ProtocolManager protocolManager : protocolManagers) {
protocolManager.stop();
}
networkExecutor.shutdown();
networkCheckExecutor.shutdown();
shutdown.countDown();
} else {
@ -118,11 +112,6 @@ public class NetworkRunner implements AutoCloseable {
for (final ProtocolManager protocolManager : protocolManagers) {
protocolManager.awaitStop();
}
if (!networkExecutor.awaitTermination(2L, TimeUnit.MINUTES)) {
LOG.error("Network executor did not shutdown cleanly.");
networkExecutor.shutdownNow();
networkExecutor.awaitTermination(2L, TimeUnit.MINUTES);
}
LOG.info("Network stopped.");
}

@ -22,7 +22,6 @@ import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
@ -63,9 +62,8 @@ public class NoopP2PNetwork implements P2PNetwork {
public void awaitStop() {}
@Override
public InetSocketAddress getDiscoverySocketAddress() {
throw new P2pDisabledException(
"P2P networking disabled. Discovery socket address unavailable.");
public Optional<Peer> getAdvertisedPeer() {
return Optional.empty();
}
@Override
@ -92,5 +90,5 @@ public class NoopP2PNetwork implements P2PNetwork {
public void close() throws IOException {}
@Override
public void run() {}
public void start() {}
}

@ -18,14 +18,15 @@ import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import java.io.Closeable;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
/** P2P Network Interface. */
public interface P2PNetwork extends Closeable, Runnable {
public interface P2PNetwork extends Closeable {
void start();
/**
* Returns a snapshot of the currently connected peer connections.
@ -44,8 +45,8 @@ public interface P2PNetwork extends Closeable, Runnable {
/**
* Subscribe a {@link Consumer} to all incoming {@link Message} of a given sub-protocol. Calling
* {@link #run()} on an implementation without at least having one subscribed {@link Consumer} per
* supported sub-protocol should throw a {@link RuntimeException}.
* {@link #start()} on an implementation without at least having one subscribed {@link Consumer}
* per supported sub-protocol should throw a {@link RuntimeException}.
*
* @param capability Capability (sub-protocol) to subscribe to.
* @param consumer Consumer to subscribe
@ -87,7 +88,7 @@ public interface P2PNetwork extends Closeable, Runnable {
/** Blocks until the P2P network layer has stopped. */
void awaitStop();
InetSocketAddress getDiscoverySocketAddress();
Optional<? extends Peer> getAdvertisedPeer();
/**
* Returns {@link PeerInfo} object for this node

@ -14,7 +14,6 @@ package tech.pegasys.pantheon.ethereum.p2p.discovery;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static tech.pegasys.pantheon.util.bytes.BytesValue.wrapBuffer;
@ -83,7 +82,6 @@ public abstract class PeerDiscoveryAgent implements DisconnectCallback {
/* This is the {@link tech.pegasys.pantheon.ethereum.p2p.Peer} object holding who we are. */
private DiscoveryPeer advertisedPeer;
private InetSocketAddress localAddress;
/* Is discovery enabled? */
private boolean isActive = false;
@ -135,7 +133,6 @@ public abstract class PeerDiscoveryAgent implements DisconnectCallback {
.thenAccept(
(InetSocketAddress localAddress) -> {
// Once listener is set up, finish initializing
this.localAddress = localAddress;
advertisedPeer =
new DiscoveryPeer(
id, config.getAdvertisedHost(), localAddress.getPort(), tcpPort);
@ -221,19 +218,14 @@ public abstract class PeerDiscoveryAgent implements DisconnectCallback {
.orElse(Collections.emptyList());
}
public DiscoveryPeer getAdvertisedPeer() {
return advertisedPeer;
public Optional<DiscoveryPeer> getAdvertisedPeer() {
return Optional.ofNullable(advertisedPeer);
}
public BytesValue getId() {
return id;
}
public InetSocketAddress localAddress() {
checkState(localAddress != null, "Uninitialized discovery agent");
return localAddress;
}
/**
* Adds an observer that will get called when a new peer is bonded with and added to the peer
* table.

@ -164,7 +164,7 @@ public class PeerDiscoveryController {
this.peerDroppedObservers = peerDroppedObservers;
}
public CompletableFuture<?> start() {
public void start() {
if (!started.compareAndSet(false, true)) {
throw new IllegalStateException("The peer table had already been started");
}
@ -199,8 +199,6 @@ public class PeerDiscoveryController {
nodeWhitelistController.ifPresent(
c -> c.subscribeToListUpdatedEvent(this::handleNodeWhitelistUpdatedEvent));
return CompletableFuture.completedFuture(null);
}
public CompletableFuture<?> stop() {

@ -467,16 +467,12 @@ public class NettyP2PNetwork implements P2PNetwork {
}
@Override
public void run() {
try {
peerDiscoveryAgent.start(ourPeerInfo.getPort()).join();
peerBondedObserverId =
OptionalLong.of(peerDiscoveryAgent.observePeerBondedEvents(handlePeerBondedEvent()));
peerDroppedObserverId =
OptionalLong.of(peerDiscoveryAgent.observePeerDroppedEvents(handlePeerDroppedEvents()));
} catch (final Exception ex) {
throw new IllegalStateException(ex);
}
public void start() {
peerDiscoveryAgent.start(ourPeerInfo.getPort()).join();
peerBondedObserverId =
OptionalLong.of(peerDiscoveryAgent.observePeerBondedEvents(handlePeerBondedEvent()));
peerDroppedObserverId =
OptionalLong.of(peerDiscoveryAgent.observePeerDroppedEvents(handlePeerDroppedEvents()));
}
private Consumer<PeerBondedEvent> handlePeerBondedEvent() {
@ -546,8 +542,8 @@ public class NettyP2PNetwork implements P2PNetwork {
}
@Override
public InetSocketAddress getDiscoverySocketAddress() {
return peerDiscoveryAgent.localAddress();
public Optional<? extends Peer> getAdvertisedPeer() {
return peerDiscoveryAgent.getAdvertisedPeer();
}
@Override

@ -18,8 +18,6 @@ import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.OptionalInt;
import org.bouncycastle.util.encoders.Hex;
public interface Peer extends PeerId {
/**
@ -60,7 +58,7 @@ public interface Peer extends PeerId {
* @return The enode URI as a String.
*/
default String getEnodeURI() {
String url = Hex.toHexString(this.getId().extractArray());
String url = this.getId().toUnprefixedString();
Endpoint endpoint = this.getEndpoint();
String nodeIp = endpoint.getHost();
OptionalInt tcpPort = endpoint.getTcpPort();

@ -105,8 +105,8 @@ public final class NettyP2PNetworkTest {
Optional.empty())) {
final int listenPort = listener.getLocalPeerInfo().getPort();
listener.run();
connector.run();
listener.start();
connector.start();
final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes();
assertThat(
connector
@ -158,8 +158,8 @@ public final class NettyP2PNetworkTest {
new NoOpMetricsSystem(),
Optional.empty())) {
final int listenPort = listener.getLocalPeerInfo().getPort();
listener.run();
connector.run();
listener.start();
connector.start();
final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes();
assertThat(
connector
@ -242,8 +242,8 @@ public final class NettyP2PNetworkTest {
final int listenPort = listener.getLocalPeerInfo().getPort();
// Setup listener and first connection
listener.run();
connector1.run();
listener.start();
connector1.start();
final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes();
final Peer listeningPeer =
new DefaultPeer(
@ -263,7 +263,7 @@ public final class NettyP2PNetworkTest {
peerFuture.complete(peerConnection);
reasonFuture.complete(reason);
});
connector2.run();
connector2.start();
assertThat(connector2.connect(listeningPeer).get(30L, TimeUnit.SECONDS).getPeer().getNodeId())
.isEqualTo(listenId);
assertThat(peerFuture.get(30L, TimeUnit.SECONDS).getPeer().getNodeId()).isEqualTo(listenId);
@ -308,8 +308,8 @@ public final class NettyP2PNetworkTest {
new NoOpMetricsSystem(),
Optional.empty())) {
final int listenPort = listener.getLocalPeerInfo().getPort();
listener.run();
connector.run();
listener.start();
connector.start();
final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes();
final Peer listenerPeer =
@ -383,8 +383,8 @@ public final class NettyP2PNetworkTest {
// Blacklist the remote peer
localBlacklist.add(remotePeer);
localNetwork.run();
remoteNetwork.run();
localNetwork.start();
remoteNetwork.start();
// Setup disconnect listener
final CompletableFuture<PeerConnection> peerFuture = new CompletableFuture<>();
@ -461,8 +461,8 @@ public final class NettyP2PNetworkTest {
localListenPort,
OptionalInt.of(localListenPort)));
localNetwork.run();
remoteNetwork.run();
localNetwork.start();
remoteNetwork.start();
// Setup disconnect listener
final CompletableFuture<PeerConnection> peerFuture = new CompletableFuture<>();

@ -26,10 +26,10 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryServiceExceptio
import tech.pegasys.pantheon.ethereum.p2p.netty.NettyP2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.util.NetworkUtility;
import java.io.IOException;
import java.util.Optional;
import java.util.OptionalInt;
import io.vertx.core.Vertx;
import org.assertj.core.api.Assertions;
@ -48,22 +48,27 @@ public class NetworkingServiceLifecycleTest {
@Test
public void createPeerDiscoveryAgent() {
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.generate();
final NetworkingConfiguration config = configWithRandomPorts();
try (final NettyP2PNetwork service =
new NettyP2PNetwork(
vertx,
keyPair,
configWithRandomPorts(),
config,
emptyList(),
() -> true,
new PeerBlacklist(),
new NoOpMetricsSystem(),
Optional.empty())) {
service.run();
final int port = service.getDiscoverySocketAddress().getPort();
service.start();
final int udpPort = service.getAdvertisedPeer().get().getEndpoint().getUdpPort();
final OptionalInt tcpPort = service.getAdvertisedPeer().get().getEndpoint().getTcpPort();
assertEquals(
(NetworkUtility.isIPv6Available() ? "/0:0:0:0:0:0:0:0:" : "/0.0.0.0:") + port,
service.getDiscoverySocketAddress().toString());
config.getDiscovery().getAdvertisedHost(),
service.getAdvertisedPeer().get().getEndpoint().getHost());
assertThat(udpPort).isNotZero();
assertThat(tcpPort).isPresent();
assertThat(tcpPort.getAsInt()).isNotZero();
assertThat(service.getDiscoveryPeers()).hasSize(0);
}
}
@ -157,9 +162,9 @@ public class NetworkingServiceLifecycleTest {
new PeerBlacklist(),
new NoOpMetricsSystem(),
Optional.empty())) {
service.run();
service.start();
service.stop();
service.run();
service.start();
}
}
@ -186,9 +191,9 @@ public class NetworkingServiceLifecycleTest {
new PeerBlacklist(),
new NoOpMetricsSystem(),
Optional.empty())) {
service1.run();
service1.start();
service1.stop();
service2.run();
service2.start();
service2.stop();
}
}
@ -206,9 +211,11 @@ public class NetworkingServiceLifecycleTest {
new PeerBlacklist(),
new NoOpMetricsSystem(),
Optional.empty())) {
service1.run();
service1.start();
final NetworkingConfiguration config = configWithRandomPorts();
config.getDiscovery().setBindPort(service1.getDiscoverySocketAddress().getPort());
config
.getDiscovery()
.setBindPort(service1.getAdvertisedPeer().get().getEndpoint().getUdpPort());
try (final NettyP2PNetwork service2 =
new NettyP2PNetwork(
vertx,
@ -220,10 +227,10 @@ public class NetworkingServiceLifecycleTest {
new NoOpMetricsSystem(),
Optional.empty())) {
try {
service2.run();
service2.start();
} catch (final Exception e) {
assertThat(e.getCause()).hasCauseExactlyInstanceOf(PeerDiscoveryServiceException.class);
assertThat(e.getCause())
assertThat(e).hasCauseExactlyInstanceOf(PeerDiscoveryServiceException.class);
assertThat(e)
.hasMessageStartingWith(
"tech.pegasys.pantheon.ethereum.p2p.discovery."
+ "PeerDiscoveryServiceException: Failed to bind Ethereum UDP discovery listener to 0.0.0.0:");

@ -31,6 +31,7 @@ import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.junit.Test;
@ -66,6 +67,7 @@ public class PeerDiscoveryAgentTest {
final List<DiscoveryPeer> otherPeers =
otherAgents.stream()
.map(MockPeerDiscoveryAgent::getAdvertisedPeer)
.map(Optional::get)
.collect(Collectors.toList());
// Start another peer pointing to those 20 agents.
@ -84,7 +86,7 @@ public class PeerDiscoveryAgentTest {
packet =
Packet.create(
PacketType.FIND_NEIGHBORS,
FindNeighborsPacketData.create(otherAgents.get(0).getAdvertisedPeer().getId()),
FindNeighborsPacketData.create(otherAgents.get(0).getAdvertisedPeer().get().getId()),
testAgent.getKeyPair());
helper.sendMessageBetweenAgents(testAgent, agent, packet);
@ -108,7 +110,7 @@ public class PeerDiscoveryAgentTest {
otherPeers.removeAll(neighbors.getNodes());
assertThat(otherPeers.size()).isBetween(4, 5);
if (otherPeers.size() == 5) {
assertThat(neighbors.getNodes()).contains(testAgent.getAdvertisedPeer());
assertThat(neighbors.getNodes()).contains(testAgent.getAdvertisedPeer().get());
}
}
@ -116,7 +118,7 @@ public class PeerDiscoveryAgentTest {
public void shouldEvictPeerOnDisconnect() {
final MockPeerDiscoveryAgent peerDiscoveryAgent1 = helper.startDiscoveryAgent();
peerDiscoveryAgent1.start(BROADCAST_TCP_PORT).join();
final DiscoveryPeer peer = peerDiscoveryAgent1.getAdvertisedPeer();
final DiscoveryPeer peer = peerDiscoveryAgent1.getAdvertisedPeer().get();
final MockPeerDiscoveryAgent peerDiscoveryAgent2 = helper.startDiscoveryAgent(peer);
peerDiscoveryAgent2.start(BROADCAST_TCP_PORT).join();

@ -50,7 +50,7 @@ public class PeerDiscoveryBondingTest {
final PongPacketData pong =
otherAgentIncomingPongs.get(0).packet.getPacketData(PongPacketData.class).get();
assertThat(pong.getTo()).isEqualTo(otherAgent.getAdvertisedPeer().getEndpoint());
assertThat(pong.getTo()).isEqualTo(otherAgent.getAdvertisedPeer().get().getEndpoint());
// The agent considers the test peer BONDED.
assertThat(agent.getPeers()).hasSize(1);
@ -87,7 +87,8 @@ public class PeerDiscoveryBondingTest {
Optional<PongPacketData> maybePongData =
incomingPongs.get(0).packet.getPacketData(PongPacketData.class);
assertThat(maybePongData).isPresent();
assertThat(maybePongData.get().getTo()).isEqualTo(otherNode.getAdvertisedPeer().getEndpoint());
assertThat(maybePongData.get().getTo())
.isEqualTo(otherNode.getAdvertisedPeer().get().getEndpoint());
// No more packets.
assertThat(otherNode.getIncomingPackets()).hasSize(0);

@ -26,6 +26,7 @@ import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.List;
import java.util.Optional;
import org.junit.Test;
@ -39,7 +40,8 @@ public class PeerDiscoveryBootstrappingTest {
final MockPeerDiscoveryAgent testAgent = helper.startDiscoveryAgent();
// Start an agent.
final PeerDiscoveryAgent agent = helper.startDiscoveryAgent(testAgent.getAdvertisedPeer());
final PeerDiscoveryAgent agent =
helper.startDiscoveryAgent(testAgent.getAdvertisedPeer().get());
final List<IncomingPacket> incomingPackets =
testAgent.getIncomingPackets().stream()
@ -47,13 +49,13 @@ public class PeerDiscoveryBootstrappingTest {
.collect(toList());
assertThat(incomingPackets.size()).isEqualTo(1);
Packet pingPacket = incomingPackets.get(0).packet;
assertThat(pingPacket.getNodeId()).isEqualTo(agent.getAdvertisedPeer().getId());
assertThat(pingPacket.getNodeId()).isEqualTo(agent.getAdvertisedPeer().get().getId());
final PingPacketData pingData = pingPacket.getPacketData(PingPacketData.class).get();
assertThat(pingData.getExpiration())
.isGreaterThanOrEqualTo(System.currentTimeMillis() / 1000 - 10000);
assertThat(pingData.getFrom()).isEqualTo(agent.getAdvertisedPeer().getEndpoint());
assertThat(pingData.getTo()).isEqualTo(testAgent.getAdvertisedPeer().getEndpoint());
assertThat(pingData.getFrom()).isEqualTo(agent.getAdvertisedPeer().get().getEndpoint());
assertThat(pingData.getTo()).isEqualTo(testAgent.getAdvertisedPeer().get().getEndpoint());
}
@Test
@ -61,7 +63,10 @@ public class PeerDiscoveryBootstrappingTest {
// Use these peers as bootstrap peers.
final List<MockPeerDiscoveryAgent> bootstrapAgents = helper.startDiscoveryAgents(3);
final List<DiscoveryPeer> bootstrapPeers =
bootstrapAgents.stream().map(PeerDiscoveryAgent::getAdvertisedPeer).collect(toList());
bootstrapAgents.stream()
.map(PeerDiscoveryAgent::getAdvertisedPeer)
.map(Optional::get)
.collect(toList());
// Start five agents.
List<MockPeerDiscoveryAgent> agents = helper.startDiscoveryAgents(5, bootstrapPeers);
@ -78,6 +83,7 @@ public class PeerDiscoveryBootstrappingTest {
final List<BytesValue> agentIds =
agents.stream()
.map(PeerDiscoveryAgent::getAdvertisedPeer)
.map(Optional::get)
.map(Peer::getId)
.distinct()
.collect(toList());
@ -95,7 +101,7 @@ public class PeerDiscoveryBootstrappingTest {
final PingPacketData ping = packet.getPacketData(PingPacketData.class).get();
assertThat(ping.getExpiration())
.isGreaterThanOrEqualTo(System.currentTimeMillis() / 1000 - 10000);
assertThat(ping.getTo()).isEqualTo(bootstrapAgent.getAdvertisedPeer().getEndpoint());
assertThat(ping.getTo()).isEqualTo(bootstrapAgent.getAdvertisedPeer().get().getEndpoint());
}
}
}
@ -107,7 +113,7 @@ public class PeerDiscoveryBootstrappingTest {
// Start other five agents, pointing to the one above as a bootstrap peer.
final List<MockPeerDiscoveryAgent> otherAgents =
helper.startDiscoveryAgents(5, singletonList(bootstrapAgent.getAdvertisedPeer()));
helper.startDiscoveryAgents(5, singletonList(bootstrapAgent.getAdvertisedPeer().get()));
final BytesValue[] otherPeersIds =
otherAgents.stream().map(PeerDiscoveryAgent::getId).toArray(BytesValue[]::new);
@ -123,7 +129,7 @@ public class PeerDiscoveryBootstrappingTest {
// and will
// bond with them, ultimately adding all 7 nodes in the network to its table.
final PeerDiscoveryAgent newAgent =
helper.startDiscoveryAgent(bootstrapAgent.getAdvertisedPeer());
helper.startDiscoveryAgent(bootstrapAgent.getAdvertisedPeer().get());
assertThat(newAgent.getPeers()).hasSize(6);
}
}

@ -23,6 +23,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -84,6 +85,7 @@ public class PeerDiscoveryObserversTest {
final List<DiscoveryPeer> peers1 =
others1.stream()
.map(MockPeerDiscoveryAgent::getAdvertisedPeer)
.map(Optional::get)
.collect(Collectors.toList());
// Create two discovery agents pointing to the above as bootstrap peers.
@ -91,6 +93,7 @@ public class PeerDiscoveryObserversTest {
final List<DiscoveryPeer> peers2 =
others2.stream()
.map(MockPeerDiscoveryAgent::getAdvertisedPeer)
.map(Optional::get)
.collect(Collectors.toList());
// A list of all peers.
@ -129,7 +132,7 @@ public class PeerDiscoveryObserversTest {
// Create 3 discovery agents with no bootstrap peers.
final List<MockPeerDiscoveryAgent> others =
helper.startDiscoveryAgents(3, Collections.emptyList());
final DiscoveryPeer peer = others.get(0).getAdvertisedPeer();
final DiscoveryPeer peer = others.get(0).getAdvertisedPeer().get();
// Create a discovery agent (which we'll assert on), using the above two peers as bootstrap
// peers.

@ -75,7 +75,8 @@ public class PeerDiscoveryTestHelper {
return Packet.create(
PacketType.PING,
PingPacketData.create(
fromAgent.getAdvertisedPeer().getEndpoint(), toAgent.getAdvertisedPeer().getEndpoint()),
fromAgent.getAdvertisedPeer().get().getEndpoint(),
toAgent.getAdvertisedPeer().get().getEndpoint()),
fromAgent.getKeyPair());
}

@ -47,7 +47,7 @@ public class PeerDiscoveryTimestampsTest {
final List<DiscoveryPeer> peers = helper.createDiscoveryPeers(keypairs);
final MockPeerDiscoveryAgent agent = mock(MockPeerDiscoveryAgent.class);
when(agent.getAdvertisedPeer()).thenReturn(peers.get(0));
when(agent.getAdvertisedPeer()).thenReturn(Optional.of(peers.get(0)));
DiscoveryPeer localPeer = peers.get(0);
KeyPair localKeyPair = keypairs.get(0);
@ -55,7 +55,7 @@ public class PeerDiscoveryTimestampsTest {
new PeerDiscoveryController(
localKeyPair,
localPeer,
new PeerTable(agent.getAdvertisedPeer().getId()),
new PeerTable(agent.getAdvertisedPeer().get().getId()),
Collections.emptyList(),
OutboundMessageHandler.NOOP,
new MockTimerUtil(),

@ -51,7 +51,7 @@ public class MockPeerDiscoveryAgent extends PeerDiscoveryAgent {
// This ensures that any data passed between agents is not shared
final Packet packetClone = Packet.decode(packet.encode());
incomingPackets.add(new IncomingPacket(fromAgent, packetClone));
handleIncomingPacket(fromAgent.getAdvertisedPeer().getEndpoint(), packetClone);
handleIncomingPacket(fromAgent.getAdvertisedPeer().get().getEndpoint(), packetClone);
}
/**

@ -16,6 +16,8 @@ import tech.pegasys.pantheon.controller.PantheonController;
import tech.pegasys.pantheon.ethereum.jsonrpc.JsonRpcHttpService;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketService;
import tech.pegasys.pantheon.ethereum.p2p.NetworkRunner;
import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.metrics.prometheus.MetricsService;
import java.io.File;
@ -112,9 +114,17 @@ public class Runner implements AutoCloseable {
private void writePantheonPortsToFile() {
final Properties properties = new Properties();
if (networkRunner.getNetwork().isListening()) {
properties.setProperty("discovery", String.valueOf(getP2pUdpPort()));
properties.setProperty("p2p", String.valueOf(getP2pTcpPort()));
if (networkRunner.getNetwork().isP2pEnabled()) {
networkRunner
.getNetwork()
.getAdvertisedPeer()
.ifPresent(
advertisedPeer -> {
final Endpoint endpoint = advertisedPeer.getEndpoint();
properties.setProperty("discovery", String.valueOf(endpoint.getUdpPort()));
});
final int tcpPort = networkRunner.getNetwork().getLocalPeerInfo().getPort();
properties.setProperty("p2p", String.valueOf(tcpPort));
}
if (getJsonRpcPort().isPresent()) {
@ -155,8 +165,8 @@ public class Runner implements AutoCloseable {
}
}
public int getP2pUdpPort() {
return networkRunner.getNetwork().getDiscoverySocketAddress().getPort();
public Optional<? extends Peer> getAdvertisedPeer() {
return networkRunner.getNetwork().getAdvertisedPeer();
}
public int getP2pTcpPort() {

@ -38,6 +38,7 @@ import tech.pegasys.pantheon.ethereum.mainnet.MainnetProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec;
import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.ethereum.storage.StorageProvider;
import tech.pegasys.pantheon.ethereum.storage.keyvalue.RocksDbStorageProvider;
@ -159,16 +160,6 @@ public final class RunnerTest {
executorService.submit(runnerAhead::execute);
// Wait for network to initialize to get the P2P UDP port
Awaitility.await()
.atMost(20, TimeUnit.SECONDS)
.ignoreExceptions()
.untilAsserted(() -> assertThat(runnerAhead.getP2pUdpPort()).isNotNull());
Awaitility.await()
.atMost(20, TimeUnit.SECONDS)
.ignoreExceptions()
.untilAsserted(() -> assertThat(runnerAhead.getP2pTcpPort()).isNotNull());
final SynchronizerConfiguration syncConfigBehind =
SynchronizerConfiguration.builder()
.syncMode(mode)
@ -193,6 +184,7 @@ public final class RunnerTest {
PrivacyParameters.noPrivacy(),
dataDirBehind,
noOpMetricsSystem);
final Peer advertisedPeer = runnerAhead.getAdvertisedPeer().get();
final EthNetworkConfig behindEthNetworkConfiguration =
new EthNetworkConfig(
EthNetworkConfig.jsonConfig(DEV),
@ -200,9 +192,9 @@ public final class RunnerTest {
Collections.singletonList(
URI.create(
new DefaultPeer(
aheadDbNodeKeys.getPublicKey().getEncodedBytes(),
listenHost,
runnerAhead.getP2pUdpPort(),
advertisedPeer.getId(),
advertisedPeer.getEndpoint().getHost(),
advertisedPeer.getEndpoint().getUdpPort(),
runnerAhead.getP2pTcpPort())
.getEnodeURI())));
final Runner runnerBehind =

@ -549,4 +549,9 @@ public interface BytesValue extends Comparable<BytesValue> {
*/
@Override
String toString();
default String toUnprefixedString() {
final String prefixedHex = toString();
return prefixedHex.startsWith("0x") ? prefixedHex.substring(2) : prefixedHex;
}
}

Loading…
Cancel
Save