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. 35
      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. 10
      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() { public void startNetworks() {
for (final TestNode node : nodes) { 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.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.p2p.P2pDisabledException; import tech.pegasys.pantheon.ethereum.p2p.P2pDisabledException;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork; import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.google.common.net.InetAddresses;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -67,25 +65,26 @@ public class AdminNodeInfo implements JsonRpcMethod {
try { try {
final Map<String, Object> response = new HashMap<>(); final Map<String, Object> response = new HashMap<>();
final BytesValue nodeId = peerNetwork.getLocalPeerInfo().getNodeId(); final Map<String, Integer> ports = new HashMap<>();
final InetSocketAddress address = peerNetwork.getDiscoverySocketAddress();
final int port = peerNetwork.getLocalPeerInfo().getPort();
final InetAddress inetAddress = address.getAddress(); 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( response.put(
"enode", "listenAddr",
"enode://" advertisedPeer.getEndpoint().getHost() + ":" + peerInfo.getPort());
+ nodeId.toString().substring(2) });
+ "@"
+ InetAddresses.toUriString(inetAddress)
+ ":"
+ port);
response.put("id", nodeId.toString().substring(2)); 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("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(); final ChainHead chainHead = blockchainQueries.getBlockchain().getChainHead();
response.put( 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.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import tech.pegasys.pantheon.config.GenesisConfigOptions; 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.queries.BlockchainQueries;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork; 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.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.uint.UInt256; import tech.pegasys.pantheon.util.uint.UInt256;
import java.net.InetSocketAddress;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -51,17 +52,19 @@ public class AdminNodeInfoTest {
private AdminNodeInfo method; private AdminNodeInfo method;
private final PeerInfo localPeer = private final BytesValue nodeId =
new PeerInfo(5, "0x0", Collections.emptyList(), 30303, BytesValue.EMPTY); BytesValue.fromHexString(
private final InetSocketAddress discoverySocketAddress = new InetSocketAddress("1.2.3.4", 7890); "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 ChainHead testChainHead = new ChainHead(Hash.EMPTY, UInt256.ONE);
private final GenesisConfigOptions genesisConfigOptions = private final GenesisConfigOptions genesisConfigOptions =
new StubGenesisConfigOptions().chainId(2019); new StubGenesisConfigOptions().chainId(2019);
private final DefaultPeer defaultPeer = new DefaultPeer(nodeId, "1.2.3.4", 7890, 30303);
@Before @Before
public void setup() { public void setup() {
when(p2pNetwork.getLocalPeerInfo()).thenReturn(localPeer); 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.getBlockchain()).thenReturn(blockchain);
when(blockchainQueries.getBlockHashByNumber(anyLong())).thenReturn(Optional.of(Hash.EMPTY)); when(blockchainQueries.getBlockHashByNumber(anyLong())).thenReturn(Optional.of(Hash.EMPTY));
when(blockchain.getChainHead()).thenReturn(testChainHead); when(blockchain.getChainHead()).thenReturn(testChainHead);
@ -77,11 +80,16 @@ public class AdminNodeInfoTest {
final JsonRpcSuccessResponse actual = (JsonRpcSuccessResponse) method.response(request); final JsonRpcSuccessResponse actual = (JsonRpcSuccessResponse) method.response(request);
final Map<String, Object> expected = new HashMap<>(); final Map<String, Object> expected = new HashMap<>();
expected.put("enode", "enode://@1.2.3.4:30303"); expected.put(
expected.put("id", ""); "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("listenAddr", "1.2.3.4:30303");
expected.put("name", "testnet/1.0/this/that"); 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( expected.put(
"protocols", "protocols",
ImmutableMap.of( 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.MessageData;
import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork; import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.api.PeerConnection; 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.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.wire.Capability; import tech.pegasys.pantheon.ethereum.p2p.wire.Capability;
import tech.pegasys.pantheon.ethereum.p2p.wire.DefaultMessage; 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.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
import java.net.InetSocketAddress;
import java.net.SocketAddress; import java.net.SocketAddress;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
@ -177,12 +177,12 @@ public final class MockNetwork {
public void awaitStop() {} public void awaitStop() {}
@Override @Override
public InetSocketAddress getDiscoverySocketAddress() { public Optional<Peer> getAdvertisedPeer() {
return null; return Optional.of(new DefaultPeer(self.getId(), "127.0.0.1", 0, 0));
} }
@Override @Override
public void run() {} public void start() {}
@Override @Override
public void close() {} public void close() {}

@ -29,7 +29,6 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -37,7 +36,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; 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 started = new AtomicBoolean(false);
private final AtomicBoolean stopped = 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 = private final ScheduledExecutorService networkCheckExecutor =
Executors.newSingleThreadScheduledExecutor(); Executors.newSingleThreadScheduledExecutor();
@ -89,7 +84,7 @@ public class NetworkRunner implements AutoCloseable {
if (started.compareAndSet(false, true)) { if (started.compareAndSet(false, true)) {
LOG.info("Starting Network."); LOG.info("Starting Network.");
setupHandlers(); setupHandlers();
networkExecutor.submit(network); network.start();
networkCheckExecutor.scheduleWithFixedDelay( networkCheckExecutor.scheduleWithFixedDelay(
network::checkMaintainedConnectionPeers, 60, 60, TimeUnit.SECONDS); network::checkMaintainedConnectionPeers, 60, 60, TimeUnit.SECONDS);
} else { } else {
@ -104,7 +99,6 @@ public class NetworkRunner implements AutoCloseable {
for (final ProtocolManager protocolManager : protocolManagers) { for (final ProtocolManager protocolManager : protocolManagers) {
protocolManager.stop(); protocolManager.stop();
} }
networkExecutor.shutdown();
networkCheckExecutor.shutdown(); networkCheckExecutor.shutdown();
shutdown.countDown(); shutdown.countDown();
} else { } else {
@ -118,11 +112,6 @@ public class NetworkRunner implements AutoCloseable {
for (final ProtocolManager protocolManager : protocolManagers) { for (final ProtocolManager protocolManager : protocolManagers) {
protocolManager.awaitStop(); 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."); LOG.info("Network stopped.");
} }

@ -22,7 +22,6 @@ import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@ -63,9 +62,8 @@ public class NoopP2PNetwork implements P2PNetwork {
public void awaitStop() {} public void awaitStop() {}
@Override @Override
public InetSocketAddress getDiscoverySocketAddress() { public Optional<Peer> getAdvertisedPeer() {
throw new P2pDisabledException( return Optional.empty();
"P2P networking disabled. Discovery socket address unavailable.");
} }
@Override @Override
@ -92,5 +90,5 @@ public class NoopP2PNetwork implements P2PNetwork {
public void close() throws IOException {} public void close() throws IOException {}
@Override @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 tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import java.io.Closeable; import java.io.Closeable;
import java.net.InetSocketAddress;
import java.util.Collection; import java.util.Collection;
import java.util.Optional; import java.util.Optional;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer; import java.util.function.Consumer;
/** P2P Network Interface. */ /** 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. * 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 * 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 * {@link #start()} on an implementation without at least having one subscribed {@link Consumer}
* supported sub-protocol should throw a {@link RuntimeException}. * per supported sub-protocol should throw a {@link RuntimeException}.
* *
* @param capability Capability (sub-protocol) to subscribe to. * @param capability Capability (sub-protocol) to subscribe to.
* @param consumer Consumer to subscribe * @param consumer Consumer to subscribe
@ -87,7 +88,7 @@ public interface P2PNetwork extends Closeable, Runnable {
/** Blocks until the P2P network layer has stopped. */ /** Blocks until the P2P network layer has stopped. */
void awaitStop(); void awaitStop();
InetSocketAddress getDiscoverySocketAddress(); Optional<? extends Peer> getAdvertisedPeer();
/** /**
* Returns {@link PeerInfo} object for this node * 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.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; 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 java.util.concurrent.TimeUnit.MILLISECONDS;
import static tech.pegasys.pantheon.util.bytes.BytesValue.wrapBuffer; 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. */ /* This is the {@link tech.pegasys.pantheon.ethereum.p2p.Peer} object holding who we are. */
private DiscoveryPeer advertisedPeer; private DiscoveryPeer advertisedPeer;
private InetSocketAddress localAddress;
/* Is discovery enabled? */ /* Is discovery enabled? */
private boolean isActive = false; private boolean isActive = false;
@ -135,7 +133,6 @@ public abstract class PeerDiscoveryAgent implements DisconnectCallback {
.thenAccept( .thenAccept(
(InetSocketAddress localAddress) -> { (InetSocketAddress localAddress) -> {
// Once listener is set up, finish initializing // Once listener is set up, finish initializing
this.localAddress = localAddress;
advertisedPeer = advertisedPeer =
new DiscoveryPeer( new DiscoveryPeer(
id, config.getAdvertisedHost(), localAddress.getPort(), tcpPort); id, config.getAdvertisedHost(), localAddress.getPort(), tcpPort);
@ -221,19 +218,14 @@ public abstract class PeerDiscoveryAgent implements DisconnectCallback {
.orElse(Collections.emptyList()); .orElse(Collections.emptyList());
} }
public DiscoveryPeer getAdvertisedPeer() { public Optional<DiscoveryPeer> getAdvertisedPeer() {
return advertisedPeer; return Optional.ofNullable(advertisedPeer);
} }
public BytesValue getId() { public BytesValue getId() {
return id; 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 * Adds an observer that will get called when a new peer is bonded with and added to the peer
* table. * table.

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

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

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

@ -105,8 +105,8 @@ public final class NettyP2PNetworkTest {
Optional.empty())) { Optional.empty())) {
final int listenPort = listener.getLocalPeerInfo().getPort(); final int listenPort = listener.getLocalPeerInfo().getPort();
listener.run(); listener.start();
connector.run(); connector.start();
final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes(); final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes();
assertThat( assertThat(
connector connector
@ -158,8 +158,8 @@ public final class NettyP2PNetworkTest {
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
Optional.empty())) { Optional.empty())) {
final int listenPort = listener.getLocalPeerInfo().getPort(); final int listenPort = listener.getLocalPeerInfo().getPort();
listener.run(); listener.start();
connector.run(); connector.start();
final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes(); final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes();
assertThat( assertThat(
connector connector
@ -242,8 +242,8 @@ public final class NettyP2PNetworkTest {
final int listenPort = listener.getLocalPeerInfo().getPort(); final int listenPort = listener.getLocalPeerInfo().getPort();
// Setup listener and first connection // Setup listener and first connection
listener.run(); listener.start();
connector1.run(); connector1.start();
final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes(); final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes();
final Peer listeningPeer = final Peer listeningPeer =
new DefaultPeer( new DefaultPeer(
@ -263,7 +263,7 @@ public final class NettyP2PNetworkTest {
peerFuture.complete(peerConnection); peerFuture.complete(peerConnection);
reasonFuture.complete(reason); reasonFuture.complete(reason);
}); });
connector2.run(); connector2.start();
assertThat(connector2.connect(listeningPeer).get(30L, TimeUnit.SECONDS).getPeer().getNodeId()) assertThat(connector2.connect(listeningPeer).get(30L, TimeUnit.SECONDS).getPeer().getNodeId())
.isEqualTo(listenId); .isEqualTo(listenId);
assertThat(peerFuture.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(), new NoOpMetricsSystem(),
Optional.empty())) { Optional.empty())) {
final int listenPort = listener.getLocalPeerInfo().getPort(); final int listenPort = listener.getLocalPeerInfo().getPort();
listener.run(); listener.start();
connector.run(); connector.start();
final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes(); final BytesValue listenId = listenKp.getPublicKey().getEncodedBytes();
final Peer listenerPeer = final Peer listenerPeer =
@ -383,8 +383,8 @@ public final class NettyP2PNetworkTest {
// Blacklist the remote peer // Blacklist the remote peer
localBlacklist.add(remotePeer); localBlacklist.add(remotePeer);
localNetwork.run(); localNetwork.start();
remoteNetwork.run(); remoteNetwork.start();
// Setup disconnect listener // Setup disconnect listener
final CompletableFuture<PeerConnection> peerFuture = new CompletableFuture<>(); final CompletableFuture<PeerConnection> peerFuture = new CompletableFuture<>();
@ -461,8 +461,8 @@ public final class NettyP2PNetworkTest {
localListenPort, localListenPort,
OptionalInt.of(localListenPort))); OptionalInt.of(localListenPort)));
localNetwork.run(); localNetwork.start();
remoteNetwork.run(); remoteNetwork.start();
// Setup disconnect listener // Setup disconnect listener
final CompletableFuture<PeerConnection> peerFuture = new CompletableFuture<>(); 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.netty.NettyP2PNetwork;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.util.NetworkUtility;
import java.io.IOException; import java.io.IOException;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt;
import io.vertx.core.Vertx; import io.vertx.core.Vertx;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
@ -48,22 +48,27 @@ public class NetworkingServiceLifecycleTest {
@Test @Test
public void createPeerDiscoveryAgent() { public void createPeerDiscoveryAgent() {
final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.generate(); final SECP256K1.KeyPair keyPair = SECP256K1.KeyPair.generate();
final NetworkingConfiguration config = configWithRandomPorts();
try (final NettyP2PNetwork service = try (final NettyP2PNetwork service =
new NettyP2PNetwork( new NettyP2PNetwork(
vertx, vertx,
keyPair, keyPair,
configWithRandomPorts(), config,
emptyList(), emptyList(),
() -> true, () -> true,
new PeerBlacklist(), new PeerBlacklist(),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
Optional.empty())) { Optional.empty())) {
service.run(); service.start();
final int port = service.getDiscoverySocketAddress().getPort(); final int udpPort = service.getAdvertisedPeer().get().getEndpoint().getUdpPort();
final OptionalInt tcpPort = service.getAdvertisedPeer().get().getEndpoint().getTcpPort();
assertEquals( assertEquals(
(NetworkUtility.isIPv6Available() ? "/0:0:0:0:0:0:0:0:" : "/0.0.0.0:") + port, config.getDiscovery().getAdvertisedHost(),
service.getDiscoverySocketAddress().toString()); service.getAdvertisedPeer().get().getEndpoint().getHost());
assertThat(udpPort).isNotZero();
assertThat(tcpPort).isPresent();
assertThat(tcpPort.getAsInt()).isNotZero();
assertThat(service.getDiscoveryPeers()).hasSize(0); assertThat(service.getDiscoveryPeers()).hasSize(0);
} }
} }
@ -157,9 +162,9 @@ public class NetworkingServiceLifecycleTest {
new PeerBlacklist(), new PeerBlacklist(),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
Optional.empty())) { Optional.empty())) {
service.run(); service.start();
service.stop(); service.stop();
service.run(); service.start();
} }
} }
@ -186,9 +191,9 @@ public class NetworkingServiceLifecycleTest {
new PeerBlacklist(), new PeerBlacklist(),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
Optional.empty())) { Optional.empty())) {
service1.run(); service1.start();
service1.stop(); service1.stop();
service2.run(); service2.start();
service2.stop(); service2.stop();
} }
} }
@ -206,9 +211,11 @@ public class NetworkingServiceLifecycleTest {
new PeerBlacklist(), new PeerBlacklist(),
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
Optional.empty())) { Optional.empty())) {
service1.run(); service1.start();
final NetworkingConfiguration config = configWithRandomPorts(); final NetworkingConfiguration config = configWithRandomPorts();
config.getDiscovery().setBindPort(service1.getDiscoverySocketAddress().getPort()); config
.getDiscovery()
.setBindPort(service1.getAdvertisedPeer().get().getEndpoint().getUdpPort());
try (final NettyP2PNetwork service2 = try (final NettyP2PNetwork service2 =
new NettyP2PNetwork( new NettyP2PNetwork(
vertx, vertx,
@ -220,10 +227,10 @@ public class NetworkingServiceLifecycleTest {
new NoOpMetricsSystem(), new NoOpMetricsSystem(),
Optional.empty())) { Optional.empty())) {
try { try {
service2.run(); service2.start();
} catch (final Exception e) { } catch (final Exception e) {
assertThat(e.getCause()).hasCauseExactlyInstanceOf(PeerDiscoveryServiceException.class); assertThat(e).hasCauseExactlyInstanceOf(PeerDiscoveryServiceException.class);
assertThat(e.getCause()) assertThat(e)
.hasMessageStartingWith( .hasMessageStartingWith(
"tech.pegasys.pantheon.ethereum.p2p.discovery." "tech.pegasys.pantheon.ethereum.p2p.discovery."
+ "PeerDiscoveryServiceException: Failed to bind Ethereum UDP discovery listener to 0.0.0.0:"); + "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.Collections;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.junit.Test; import org.junit.Test;
@ -66,6 +67,7 @@ public class PeerDiscoveryAgentTest {
final List<DiscoveryPeer> otherPeers = final List<DiscoveryPeer> otherPeers =
otherAgents.stream() otherAgents.stream()
.map(MockPeerDiscoveryAgent::getAdvertisedPeer) .map(MockPeerDiscoveryAgent::getAdvertisedPeer)
.map(Optional::get)
.collect(Collectors.toList()); .collect(Collectors.toList());
// Start another peer pointing to those 20 agents. // Start another peer pointing to those 20 agents.
@ -84,7 +86,7 @@ public class PeerDiscoveryAgentTest {
packet = packet =
Packet.create( Packet.create(
PacketType.FIND_NEIGHBORS, PacketType.FIND_NEIGHBORS,
FindNeighborsPacketData.create(otherAgents.get(0).getAdvertisedPeer().getId()), FindNeighborsPacketData.create(otherAgents.get(0).getAdvertisedPeer().get().getId()),
testAgent.getKeyPair()); testAgent.getKeyPair());
helper.sendMessageBetweenAgents(testAgent, agent, packet); helper.sendMessageBetweenAgents(testAgent, agent, packet);
@ -108,7 +110,7 @@ public class PeerDiscoveryAgentTest {
otherPeers.removeAll(neighbors.getNodes()); otherPeers.removeAll(neighbors.getNodes());
assertThat(otherPeers.size()).isBetween(4, 5); assertThat(otherPeers.size()).isBetween(4, 5);
if (otherPeers.size() == 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() { public void shouldEvictPeerOnDisconnect() {
final MockPeerDiscoveryAgent peerDiscoveryAgent1 = helper.startDiscoveryAgent(); final MockPeerDiscoveryAgent peerDiscoveryAgent1 = helper.startDiscoveryAgent();
peerDiscoveryAgent1.start(BROADCAST_TCP_PORT).join(); peerDiscoveryAgent1.start(BROADCAST_TCP_PORT).join();
final DiscoveryPeer peer = peerDiscoveryAgent1.getAdvertisedPeer(); final DiscoveryPeer peer = peerDiscoveryAgent1.getAdvertisedPeer().get();
final MockPeerDiscoveryAgent peerDiscoveryAgent2 = helper.startDiscoveryAgent(peer); final MockPeerDiscoveryAgent peerDiscoveryAgent2 = helper.startDiscoveryAgent(peer);
peerDiscoveryAgent2.start(BROADCAST_TCP_PORT).join(); peerDiscoveryAgent2.start(BROADCAST_TCP_PORT).join();

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

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

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

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

@ -51,7 +51,7 @@ public class MockPeerDiscoveryAgent extends PeerDiscoveryAgent {
// This ensures that any data passed between agents is not shared // This ensures that any data passed between agents is not shared
final Packet packetClone = Packet.decode(packet.encode()); final Packet packetClone = Packet.decode(packet.encode());
incomingPackets.add(new IncomingPacket(fromAgent, packetClone)); 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.JsonRpcHttpService;
import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketService; import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.WebSocketService;
import tech.pegasys.pantheon.ethereum.p2p.NetworkRunner; 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 tech.pegasys.pantheon.metrics.prometheus.MetricsService;
import java.io.File; import java.io.File;
@ -112,9 +114,17 @@ public class Runner implements AutoCloseable {
private void writePantheonPortsToFile() { private void writePantheonPortsToFile() {
final Properties properties = new Properties(); final Properties properties = new Properties();
if (networkRunner.getNetwork().isListening()) { if (networkRunner.getNetwork().isP2pEnabled()) {
properties.setProperty("discovery", String.valueOf(getP2pUdpPort())); networkRunner
properties.setProperty("p2p", String.valueOf(getP2pTcpPort())); .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()) { if (getJsonRpcPort().isPresent()) {
@ -155,8 +165,8 @@ public class Runner implements AutoCloseable {
} }
} }
public int getP2pUdpPort() { public Optional<? extends Peer> getAdvertisedPeer() {
return networkRunner.getNetwork().getDiscoverySocketAddress().getPort(); return networkRunner.getNetwork().getAdvertisedPeer();
} }
public int getP2pTcpPort() { 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.ProtocolSchedule;
import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSpec;
import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer; 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.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.ethereum.storage.StorageProvider; import tech.pegasys.pantheon.ethereum.storage.StorageProvider;
import tech.pegasys.pantheon.ethereum.storage.keyvalue.RocksDbStorageProvider; import tech.pegasys.pantheon.ethereum.storage.keyvalue.RocksDbStorageProvider;
@ -159,16 +160,6 @@ public final class RunnerTest {
executorService.submit(runnerAhead::execute); 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 = final SynchronizerConfiguration syncConfigBehind =
SynchronizerConfiguration.builder() SynchronizerConfiguration.builder()
.syncMode(mode) .syncMode(mode)
@ -193,6 +184,7 @@ public final class RunnerTest {
PrivacyParameters.noPrivacy(), PrivacyParameters.noPrivacy(),
dataDirBehind, dataDirBehind,
noOpMetricsSystem); noOpMetricsSystem);
final Peer advertisedPeer = runnerAhead.getAdvertisedPeer().get();
final EthNetworkConfig behindEthNetworkConfiguration = final EthNetworkConfig behindEthNetworkConfiguration =
new EthNetworkConfig( new EthNetworkConfig(
EthNetworkConfig.jsonConfig(DEV), EthNetworkConfig.jsonConfig(DEV),
@ -200,9 +192,9 @@ public final class RunnerTest {
Collections.singletonList( Collections.singletonList(
URI.create( URI.create(
new DefaultPeer( new DefaultPeer(
aheadDbNodeKeys.getPublicKey().getEncodedBytes(), advertisedPeer.getId(),
listenHost, advertisedPeer.getEndpoint().getHost(),
runnerAhead.getP2pUdpPort(), advertisedPeer.getEndpoint().getUdpPort(),
runnerAhead.getP2pTcpPort()) runnerAhead.getP2pTcpPort())
.getEnodeURI()))); .getEnodeURI())));
final Runner runnerBehind = final Runner runnerBehind =

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

Loading…
Cancel
Save