diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNodeList.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNodeList.java index 60ebbb090c..372ff65566 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNodeList.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TestNodeList.java @@ -59,12 +59,6 @@ public TestNode create( return node; } - public void startNetworks() { - for (final TestNode node : nodes) { - node.network.start(); - } - } - public void connectAndAssertAll() throws InterruptedException, ExecutionException, TimeoutException { for (int i = 0; i < nodes.size(); i++) { diff --git a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TransactionPoolPropagationTest.java b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TransactionPoolPropagationTest.java index db3989d57d..de8856cd14 100644 --- a/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TransactionPoolPropagationTest.java +++ b/ethereum/eth/src/test/java/tech/pegasys/pantheon/ethereum/eth/transactions/TransactionPoolPropagationTest.java @@ -47,7 +47,6 @@ public void tearDown() { /** Helper to do common setup tasks. */ private void initTest(final TestNodeList txNodes) throws Exception { - txNodes.startNetworks(); txNodes.connectAndAssertAll(); txNodes.logPeerConnections(); txNodes.assertPeerCounts(); diff --git a/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminAddPeer.java b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminAddPeer.java index eef58fa12d..57592224e1 100644 --- a/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminAddPeer.java +++ b/ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminAddPeer.java @@ -13,12 +13,8 @@ package tech.pegasys.pantheon.ethereum.jsonrpc.internal.methods; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter; -import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcError; -import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcErrorResponse; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse; -import tech.pegasys.pantheon.ethereum.p2p.ConnectingToLocalNodeException; -import tech.pegasys.pantheon.ethereum.p2p.PeerNotPermittedException; import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork; import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; @@ -42,17 +38,10 @@ public String getName() { @Override protected JsonRpcResponse performOperation(final Object id, final String enode) { - try { - LOG.debug("Adding ({}) to peers", enode); - final EnodeURL enodeURL = EnodeURL.fromString(enode); - final Peer peer = DefaultPeer.fromEnodeURL(enodeURL); - boolean addedToNetwork = peerNetwork.addMaintainConnectionPeer(peer); - return new JsonRpcSuccessResponse(id, addedToNetwork); - } catch (final PeerNotPermittedException e) { - return new JsonRpcErrorResponse( - id, JsonRpcError.NON_PERMITTED_NODE_CANNOT_BE_ADDED_AS_A_PEER); - } catch (final ConnectingToLocalNodeException e) { - return new JsonRpcErrorResponse(id, JsonRpcError.CANT_CONNECT_TO_LOCAL_PEER); - } + LOG.debug("Adding ({}) to peers", enode); + final EnodeURL enodeURL = EnodeURL.fromString(enode); + final Peer peer = DefaultPeer.fromEnodeURL(enodeURL); + boolean addedToNetwork = peerNetwork.addMaintainConnectionPeer(peer); + return new JsonRpcSuccessResponse(id, addedToNetwork); } } diff --git a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminAddPeerTest.java b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminAddPeerTest.java index 46a467b806..79dac1b961 100644 --- a/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminAddPeerTest.java +++ b/ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/AdminAddPeerTest.java @@ -22,9 +22,7 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcErrorResponse; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcSuccessResponse; -import tech.pegasys.pantheon.ethereum.p2p.ConnectingToLocalNodeException; import tech.pegasys.pantheon.ethereum.p2p.P2pDisabledException; -import tech.pegasys.pantheon.ethereum.p2p.PeerNotPermittedException; import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork; import org.junit.Before; @@ -151,31 +149,4 @@ public void requestReturnsErrorWhenP2pDisabled() { assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); } - - @Test - public void requestReturnsErrorWhenPeerNotWhitelisted() { - when(p2pNetwork.addMaintainConnectionPeer(any())).thenThrow(new PeerNotPermittedException()); - - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse( - validRequest.getId(), JsonRpcError.NON_PERMITTED_NODE_CANNOT_BE_ADDED_AS_A_PEER); - - final JsonRpcResponse actualResponse = method.response(validRequest); - - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - } - - @Test - public void - p2pNetworkThrowsConnectingToLocalNodeExceptionReturnsCantConnectToLocalNodeJsonError() { - when(p2pNetwork.addMaintainConnectionPeer(any())) - .thenThrow(new ConnectingToLocalNodeException()); - - final JsonRpcResponse expectedResponse = - new JsonRpcErrorResponse(validRequest.getId(), JsonRpcError.CANT_CONNECT_TO_LOCAL_PEER); - - final JsonRpcResponse actualResponse = method.response(validRequest); - - assertThat(actualResponse).isEqualToComparingFieldByField(expectedResponse); - } } diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/ConnectingToLocalNodeException.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/ConnectingToLocalNodeException.java deleted file mode 100644 index 96a898ca3a..0000000000 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/ConnectingToLocalNodeException.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2019 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package tech.pegasys.pantheon.ethereum.p2p; - -public class ConnectingToLocalNodeException extends RuntimeException { - public ConnectingToLocalNodeException(final String message) { - super(message); - } - - public ConnectingToLocalNodeException() { - super("Cannot add the local node as a peer connection"); - } -} diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/InsufficientPeersPermissioningProvider.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/InsufficientPeersPermissioningProvider.java index 4ef2897f33..c6d02f3d6b 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/InsufficientPeersPermissioningProvider.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/InsufficientPeersPermissioningProvider.java @@ -21,13 +21,14 @@ import java.util.Collection; import java.util.Optional; +import java.util.function.Supplier; /** * A permissioning provider that only provides an answer when we have no peers outside of our * bootnodes */ public class InsufficientPeersPermissioningProvider implements ContextualNodePermissioningProvider { - private final EnodeURL selfEnode; + private final Supplier> selfEnode; private final P2PNetwork p2pNetwork; private final Collection bootnodeEnodes; private long nonBootnodePeerConnections; @@ -37,12 +38,13 @@ public class InsufficientPeersPermissioningProvider implements ContextualNodePer * Creates the provider observing the provided p2p network * * @param p2pNetwork the p2p network to observe - * @param selfEnode the advertised enode address of this node + * @param selfEnode A supplier that provides a representation of the locally running node, if + * available * @param bootnodeEnodes the bootnodes that this node is configured to connection to */ public InsufficientPeersPermissioningProvider( final P2PNetwork p2pNetwork, - final EnodeURL selfEnode, + final Supplier> selfEnode, final Collection bootnodeEnodes) { this.selfEnode = selfEnode; this.p2pNetwork = p2pNetwork; @@ -64,17 +66,23 @@ private long countP2PNetworkNonBootnodeConnections() { @Override public Optional isPermitted( final EnodeURL sourceEnode, final EnodeURL destinationEnode) { + Optional maybeSelfEnode = selfEnode.get(); if (nonBootnodePeerConnections > 0) { return Optional.empty(); - } else if (checkEnode(sourceEnode) && checkEnode(destinationEnode)) { + } else if (!maybeSelfEnode.isPresent()) { + // The local node is not yet ready, so we can't validate enodes yet + return Optional.empty(); + } else if (checkEnode(maybeSelfEnode.get(), sourceEnode) + && checkEnode(maybeSelfEnode.get(), destinationEnode)) { return Optional.of(true); } else { return Optional.empty(); } } - private boolean checkEnode(final EnodeURL enode) { - return (enode.sameEndpoint(selfEnode) || bootnodeEnodes.stream().anyMatch(enode::sameEndpoint)); + private boolean checkEnode(final EnodeURL localEnode, final EnodeURL enode) { + return (enode.sameEndpoint(localEnode) + || bootnodeEnodes.stream().anyMatch(enode::sameEndpoint)); } private void handleConnect(final PeerConnection peerConnection) { diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/PeerNotPermittedException.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/PeerNotPermittedException.java deleted file mode 100644 index c14955f605..0000000000 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/PeerNotPermittedException.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2019 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package tech.pegasys.pantheon.ethereum.p2p; - -public class PeerNotPermittedException extends RuntimeException { - public PeerNotPermittedException(final String message) { - super(message); - } - - public PeerNotPermittedException() { - super("Cannot add a peer that is not permitted"); - } -} diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/api/P2PNetwork.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/api/P2PNetwork.java index 03250ae1fc..aee2c95e4f 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/api/P2PNetwork.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/api/P2PNetwork.java @@ -77,21 +77,23 @@ public interface P2PNetwork extends Closeable { void subscribeDisconnect(DisconnectCallback consumer); /** - * Adds a {@link Peer} to a list indicating efforts should be made to always stay connected to it + * Adds a {@link Peer} to a list indicating efforts should be made to always stay connected + * regardless of maxPeer limits. Non-permitted peers may be added to this list, but will not + * actually be connected to as long as they are prohibited. * * @param peer The peer that should be connected to - * @return boolean representing whether or not the peer has been added to the list or was already - * on it + * @return boolean representing whether or not the peer has been added to the list, false is + * returned if the peer was already on the list */ boolean addMaintainConnectionPeer(final Peer peer); /** - * Removes a {@link Peer} from a list indicating any existing efforts to connect to a given peer - * should be removed, and if connected, the peer should be disconnected + * Disconnect and remove the given {@link Peer} from the maintained peer list. Peer is + * disconnected even if it is not in the maintained peer list. See {@link + * #addMaintainConnectionPeer(Peer)} for details on the maintained peer list. * * @param peer The peer to which connections are not longer required - * @return boolean representing whether or not the peer has been disconnected, or if it was not - * currently connected. + * @return boolean representing whether the peer was removed from the maintained peer list */ boolean removeMaintainedConnectionPeer(final Peer peer); diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetwork.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetwork.java index f4ae8474e9..29a2e8d7f9 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetwork.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetwork.java @@ -19,8 +19,6 @@ import tech.pegasys.pantheon.crypto.SECP256K1.KeyPair; import tech.pegasys.pantheon.ethereum.chain.BlockAddedEvent; import tech.pegasys.pantheon.ethereum.chain.Blockchain; -import tech.pegasys.pantheon.ethereum.p2p.ConnectingToLocalNodeException; -import tech.pegasys.pantheon.ethereum.p2p.PeerNotPermittedException; import tech.pegasys.pantheon.ethereum.p2p.api.DisconnectCallback; import tech.pegasys.pantheon.ethereum.p2p.api.Message; import tech.pegasys.pantheon.ethereum.p2p.api.P2PNetwork; @@ -71,6 +69,7 @@ import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; import java.util.function.Supplier; import java.util.stream.Collectors; @@ -182,12 +181,14 @@ public class DefaultP2PNetwork implements P2PNetwork { private final String advertisedHost; - private volatile EnodeURL ourEnodeURL; + private volatile Optional localEnode = Optional.empty(); private final Optional nodePermissioningController; private final Optional blockchain; private OptionalLong blockAddedObserverId = OptionalLong.empty(); + private final AtomicBoolean started = new AtomicBoolean(false); + /** * Creates a peer networking service for production purposes. * @@ -346,7 +347,7 @@ protected void initChannel(final SocketChannel ch) { return; } - if (!isPeerConnectionAllowed(connection)) { + if (!isPeerAllowed(connection)) { connection.disconnect(DisconnectReason.UNKNOWN); return; } @@ -362,21 +363,13 @@ protected void initChannel(final SocketChannel ch) { @Override public boolean addMaintainConnectionPeer(final Peer peer) { - if (!isPeerAllowed(peer)) { - throw new PeerNotPermittedException(); - } - - if (peer.getId().equals(ourPeerInfo.getNodeId())) { - throw new ConnectingToLocalNodeException(); - } - final boolean added = peerMaintainConnectionList.add(peer); - if (added) { + if (isPeerAllowed(peer) && !isConnectingOrConnected(peer)) { + // Connect immediately if appropriate connect(peer); - return true; - } else { - return false; } + + return added; } @Override @@ -394,12 +387,11 @@ public boolean removeMaintainedConnectionPeer(final Peer peer) { return removed; } - public void checkMaintainedConnectionPeers() { - for (final Peer peer : peerMaintainConnectionList) { - if (!(isConnecting(peer) || isConnected(peer))) { - connect(peer); - } - } + void checkMaintainedConnectionPeers() { + peerMaintainConnectionList.stream() + .filter(p -> !isConnectingOrConnected(p)) + .filter(this::isPeerAllowed) + .forEach(this::connect); } @VisibleForTesting @@ -529,6 +521,10 @@ public void subscribeDisconnect(final DisconnectCallback callback) { @Override public void start() { + if (!started.compareAndSet(false, true)) { + LOG.warn("Attempted to start an already started " + getClass().getSimpleName()); + } + peerDiscoveryAgent.start(ourPeerInfo.getPort()).join(); peerBondedObserverId = OptionalLong.of(peerDiscoveryAgent.observePeerBondedEvents(handlePeerBondedEvent())); @@ -549,11 +545,10 @@ public void start() { } } - this.ourEnodeURL = buildSelfEnodeURL(); - LOG.info("Enode URL {}", ourEnodeURL.toString()); + createLocalEnode(); peerConnectionScheduler.scheduleWithFixedDelay( - this::checkMaintainedConnectionPeers, 60, 60, TimeUnit.SECONDS); + this::checkMaintainedConnectionPeers, 2, 60, TimeUnit.SECONDS); peerConnectionScheduler.scheduleWithFixedDelay( this::attemptPeerConnections, 30, 30, TimeUnit.SECONDS); } @@ -584,7 +579,7 @@ private synchronized void handleBlockAddedEvent( .getPeerConnections() .forEach( peerConnection -> { - if (!isPeerConnectionAllowed(peerConnection)) { + if (!isPeerAllowed(peerConnection)) { peerConnection.disconnect(DisconnectReason.REQUESTED); } }); @@ -595,38 +590,36 @@ private synchronized void checkCurrentConnections() { .getPeerConnections() .forEach( peerConnection -> { - if (!isPeerConnectionAllowed(peerConnection)) { + if (!isPeerAllowed(peerConnection)) { peerConnection.disconnect(DisconnectReason.REQUESTED); } }); } - private boolean isPeerConnectionAllowed(final PeerConnection peerConnection) { - if (peerBlacklist.contains(peerConnection)) { - return false; - } - - LOG.trace( - "Checking if connection with peer {} is permitted", - peerConnection.getPeerInfo().getNodeId()); - - return nodePermissioningController - .map( - c -> { - final EnodeURL localPeerEnodeURL = getLocalEnode().orElse(buildSelfEnodeURL()); - final EnodeURL remotePeerEnodeURL = peerConnection.getRemoteEnode(); - return c.isPermitted(localPeerEnodeURL, remotePeerEnodeURL); - }) - .orElse(true); + private boolean isPeerAllowed(final PeerConnection conn) { + return isPeerAllowed(conn.getRemoteEnode()); } private boolean isPeerAllowed(final Peer peer) { - if (peerBlacklist.contains(peer)) { + return isPeerAllowed(peer.getEnodeURL()); + } + + private boolean isPeerAllowed(final EnodeURL enode) { + if (peerBlacklist.contains(enode.getNodeId())) { + return false; + } + if (enode.getNodeId().equals(ourPeerInfo.getNodeId())) { + // Peer matches our node id return false; } + Optional maybeEnode = getLocalEnode(); + if (!maybeEnode.isPresent()) { + // If local enode isn't yet available we can't evaluate permissions + return false; + } return nodePermissioningController - .map(c -> c.isPermitted(ourEnodeURL, peer.getEnodeURL())) + .map(c -> c.isPermitted(maybeEnode.get(), enode)) .orElse(true); } @@ -640,6 +633,10 @@ boolean isConnected(final Peer peer) { return connections.isAlreadyConnected(peer.getId()); } + private boolean isConnectingOrConnected(final Peer peer) { + return isConnected(peer) || isConnecting(peer); + } + @Override public void stop() { sendClientQuittingToPeers(); @@ -691,10 +688,14 @@ public boolean isDiscoveryEnabled() { @Override public Optional getLocalEnode() { - return Optional.ofNullable(ourEnodeURL); + return localEnode; } - private EnodeURL buildSelfEnodeURL() { + private void createLocalEnode() { + if (localEnode.isPresent()) { + return; + } + final BytesValue nodeId = ourPeerInfo.getNodeId(); final int listeningPort = ourPeerInfo.getPort(); final OptionalInt discoveryPort = @@ -704,12 +705,16 @@ private EnodeURL buildSelfEnodeURL() { .filter(port -> port.getAsInt() != listeningPort) .orElse(OptionalInt.empty()); - return EnodeURL.builder() - .nodeId(nodeId) - .ipAddress(advertisedHost) - .listeningPort(listeningPort) - .discoveryPort(discoveryPort) - .build(); + final EnodeURL localEnode = + EnodeURL.builder() + .nodeId(nodeId) + .ipAddress(advertisedHost) + .listeningPort(listeningPort) + .discoveryPort(discoveryPort) + .build(); + + LOG.info("Enode URL {}", localEnode.toString()); + this.localEnode = Optional.of(localEnode); } private void onConnectionEstablished(final PeerConnection connection) { @@ -719,14 +724,14 @@ private void onConnectionEstablished(final PeerConnection connection) { public static class Builder { - protected PeerDiscoveryAgent peerDiscoveryAgent; - protected KeyPair keyPair; - protected NetworkingConfiguration config = NetworkingConfiguration.create(); - protected List supportedCapabilities; - protected PeerBlacklist peerBlacklist; - protected MetricsSystem metricsSystem; - protected Optional nodePermissioningController = Optional.empty(); - protected Blockchain blockchain = null; + private PeerDiscoveryAgent peerDiscoveryAgent; + private KeyPair keyPair; + private NetworkingConfiguration config = NetworkingConfiguration.create(); + private List supportedCapabilities; + private PeerBlacklist peerBlacklist; + private MetricsSystem metricsSystem; + private Optional nodePermissioningController = Optional.empty(); + private Blockchain blockchain = null; private Vertx vertx; private Optional nodeLocalConfigPermissioningController = Optional.empty(); diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/peers/PeerBlacklist.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/peers/PeerBlacklist.java index d997f1dae3..9a84be454f 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/peers/PeerBlacklist.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/peers/PeerBlacklist.java @@ -79,7 +79,7 @@ public PeerBlacklist() { this(DEFAULT_BLACKLIST_CAP, Collections.emptySet()); } - private boolean contains(final BytesValue nodeId) { + public boolean contains(final BytesValue nodeId) { return blacklistedNodeIds.contains(nodeId) || bannedNodeIds.contains(nodeId); } diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/InsufficientPeersPermissioningProviderTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/InsufficientPeersPermissioningProviderTest.java index 183e4f85c6..0cced86e6a 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/InsufficientPeersPermissioningProviderTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/InsufficientPeersPermissioningProviderTest.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Optional; import java.util.function.Consumer; import org.junit.Test; @@ -60,7 +61,8 @@ public void noResultWhenNoBootnodes() { when(p2pNetwork.getPeers()).thenReturn(Collections.emptyList()); final InsufficientPeersPermissioningProvider provider = - new InsufficientPeersPermissioningProvider(p2pNetwork, SELF_ENODE, bootnodes); + new InsufficientPeersPermissioningProvider( + p2pNetwork, () -> Optional.of(SELF_ENODE), bootnodes); assertThat(provider.isPermitted(SELF_ENODE, ENODE_2)).isEmpty(); } @@ -74,7 +76,8 @@ public void noResultWhenOtherConnections() { final Collection bootnodes = Collections.singletonList(ENODE_2); final InsufficientPeersPermissioningProvider provider = - new InsufficientPeersPermissioningProvider(p2pNetwork, SELF_ENODE, bootnodes); + new InsufficientPeersPermissioningProvider( + p2pNetwork, () -> Optional.of(SELF_ENODE), bootnodes); assertThat(provider.isPermitted(SELF_ENODE, ENODE_3)).isEmpty(); assertThat(provider.isPermitted(SELF_ENODE, ENODE_2)).isEmpty(); @@ -87,12 +90,26 @@ public void allowsConnectionIfBootnodeAndNoConnections() { when(p2pNetwork.getPeers()).thenReturn(Collections.emptyList()); final InsufficientPeersPermissioningProvider provider = - new InsufficientPeersPermissioningProvider(p2pNetwork, SELF_ENODE, bootnodes); + new InsufficientPeersPermissioningProvider( + p2pNetwork, () -> Optional.of(SELF_ENODE), bootnodes); assertThat(provider.isPermitted(SELF_ENODE, ENODE_2)).contains(true); assertThat(provider.isPermitted(SELF_ENODE, ENODE_3)).isEmpty(); } + @Test + public void noResultWhenLocalNodeNotReady() { + final Collection bootnodes = Collections.singletonList(ENODE_2); + + when(p2pNetwork.getPeers()).thenReturn(Collections.emptyList()); + + final InsufficientPeersPermissioningProvider provider = + new InsufficientPeersPermissioningProvider(p2pNetwork, Optional::empty, bootnodes); + + assertThat(provider.isPermitted(SELF_ENODE, ENODE_2)).isEmpty(); + assertThat(provider.isPermitted(SELF_ENODE, ENODE_3)).isEmpty(); + } + @Test public void allowsConnectionIfBootnodeAndOnlyBootnodesConnected() { final Collection bootnodes = Collections.singletonList(ENODE_2); @@ -102,7 +119,8 @@ public void allowsConnectionIfBootnodeAndOnlyBootnodesConnected() { when(p2pNetwork.getPeers()).thenReturn(Collections.singletonList(bootnodeMatchPeerConnection)); final InsufficientPeersPermissioningProvider provider = - new InsufficientPeersPermissioningProvider(p2pNetwork, SELF_ENODE, bootnodes); + new InsufficientPeersPermissioningProvider( + p2pNetwork, () -> Optional.of(SELF_ENODE), bootnodes); assertThat(provider.isPermitted(SELF_ENODE, ENODE_2)).contains(true); assertThat(provider.isPermitted(SELF_ENODE, ENODE_3)).isEmpty(); @@ -125,7 +143,8 @@ public void firesUpdateWhenDisconnectLastNonBootnode() { when(p2pNetwork.getPeers()).thenReturn(pcs); final InsufficientPeersPermissioningProvider provider = - new InsufficientPeersPermissioningProvider(p2pNetwork, SELF_ENODE, bootnodes); + new InsufficientPeersPermissioningProvider( + p2pNetwork, () -> Optional.of(SELF_ENODE), bootnodes); final ArgumentCaptor callbackCaptor = ArgumentCaptor.forClass(DisconnectCallback.class); @@ -152,7 +171,8 @@ public void firesUpdateWhenNonBootnodeConnects() { when(p2pNetwork.getPeers()).thenReturn(pcs); final InsufficientPeersPermissioningProvider provider = - new InsufficientPeersPermissioningProvider(p2pNetwork, SELF_ENODE, bootnodes); + new InsufficientPeersPermissioningProvider( + p2pNetwork, () -> Optional.of(SELF_ENODE), bootnodes); @SuppressWarnings("unchecked") final ArgumentCaptor> callbackCaptor = @@ -185,7 +205,8 @@ public void firesUpdateWhenGettingAndLosingConnection() { when(p2pNetwork.getPeers()).thenReturn(pcs); final InsufficientPeersPermissioningProvider provider = - new InsufficientPeersPermissioningProvider(p2pNetwork, SELF_ENODE, bootnodes); + new InsufficientPeersPermissioningProvider( + p2pNetwork, () -> Optional.of(SELF_ENODE), bootnodes); @SuppressWarnings("unchecked") final ArgumentCaptor> connectCallbackCaptor = diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java index 5e11023b3b..29ffa6ae99 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java @@ -1074,7 +1074,8 @@ public void whenObservingNodeWhitelistAndNodeIsRemovedShouldEvictPeerFromPeerTab final URI peerURI = URI.create(peer.getEnodeURLString()); config.setNodeWhitelist(Lists.newArrayList(peerURI)); final NodeLocalConfigPermissioningController nodeLocalConfigPermissioningController = - new NodeLocalConfigPermissioningController(config, Collections.emptyList(), selfEnode); + new NodeLocalConfigPermissioningController( + config, Collections.emptyList(), selfEnode.getNodeId()); controller = getControllerBuilder() @@ -1101,7 +1102,8 @@ public void whenObservingNodeWhitelistAndNodeIsRemovedShouldNotifyPeerDroppedObs final URI peerURI = URI.create(peer.getEnodeURLString()); config.setNodeWhitelist(Lists.newArrayList(peerURI)); final NodeLocalConfigPermissioningController nodeLocalConfigPermissioningController = - new NodeLocalConfigPermissioningController(config, Collections.emptyList(), selfEnode); + new NodeLocalConfigPermissioningController( + config, Collections.emptyList(), selfEnode.getNodeId()); final Consumer peerDroppedEventConsumer = mock(Consumer.class); final Subscribers> peerDroppedSubscribers = new Subscribers(); diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetworkTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetworkTest.java index 7fc9e80e3a..e25484835c 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetworkTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/DefaultP2PNetworkTest.java @@ -103,6 +103,7 @@ public void closeVertx() { @Test public void addingMaintainedNetworkPeerStartsConnection() { final DefaultP2PNetwork network = mockNetwork(); + network.start(); final Peer peer = mockPeer(); assertThat(network.addMaintainConnectionPeer(peer)).isTrue(); @@ -114,6 +115,7 @@ public void addingMaintainedNetworkPeerStartsConnection() { @Test public void addingRepeatMaintainedPeersReturnsFalse() { final P2PNetwork network = network(); + network.start(); final Peer peer = mockPeer(); assertThat(network.addMaintainConnectionPeer(peer)).isTrue(); assertThat(network.addMaintainConnectionPeer(peer)).isFalse(); @@ -122,6 +124,8 @@ public void addingRepeatMaintainedPeersReturnsFalse() { @Test public void checkMaintainedConnectionPeersTriesToConnect() { final DefaultP2PNetwork network = mockNetwork(); + network.start(); + final Peer peer = mockPeer(); network.peerMaintainConnectionList.add(peer); @@ -129,6 +133,20 @@ public void checkMaintainedConnectionPeersTriesToConnect() { verify(network, times(1)).connect(peer); } + @Test + public void checkMaintainedConnectionPeersDoesNotConnectToDisallowedPeer() { + final DefaultP2PNetwork network = mockNetwork(); + network.start(); + + // Add peer that is not permitted + final Peer peer = mockPeer(); + lenient().when(nodePermissioningController.isPermitted(any(), any())).thenReturn(false); + network.peerMaintainConnectionList.add(peer); + + network.checkMaintainedConnectionPeers(); + verify(network, never()).connect(peer); + } + @Test public void checkMaintainedConnectionPeersDoesntReconnectPendingPeers() { final DefaultP2PNetwork network = mockNetwork(); @@ -143,24 +161,21 @@ public void checkMaintainedConnectionPeersDoesntReconnectPendingPeers() { @Test public void checkMaintainedConnectionPeersDoesntReconnectConnectedPeers() { final DefaultP2PNetwork network = spy(network()); + network.start(); final Peer peer = mockPeer(); + + // Connect to Peer verify(network, never()).connect(peer); - assertThat(network.addMaintainConnectionPeer(peer)).isTrue(); + network.connect(peer); verify(network, times(1)).connect(peer); - { - final CompletableFuture connection; - connection = network.pendingConnections.remove(peer); - assertThat(connection).isNotNull(); - assertThat(connection.cancel(true)).isTrue(); - } + // Add peer to maintained list + assertThat(network.addMaintainConnectionPeer(peer)).isTrue(); + verify(network, times(1)).connect(peer); - { - final PeerConnection peerConnection = mockPeerConnection(peer.getId()); - network.connections.registerConnection(peerConnection); - network.checkMaintainedConnectionPeers(); - verify(network, times(1)).connect(peer); - } + // Check maintained connections + network.checkMaintainedConnectionPeers(); + verify(network, times(1)).connect(peer); } @Test diff --git a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/P2PNetworkTest.java b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/P2PNetworkTest.java index 65089adab4..4c96180227 100644 --- a/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/P2PNetworkTest.java +++ b/ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/network/P2PNetworkTest.java @@ -319,7 +319,8 @@ public void rejectIncomingConnectionFromNonWhitelistedPeer() throws Exception { config.setNodePermissioningConfigFilePath(tempFile.toAbsolutePath().toString()); final NodeLocalConfigPermissioningController localWhitelistController = - new NodeLocalConfigPermissioningController(config, Collections.emptyList(), selfEnode); + new NodeLocalConfigPermissioningController( + config, Collections.emptyList(), selfEnode.getNodeId()); // turn on whitelisting by adding a different node NOT remote node localWhitelistController.addNode( EnodeURL.builder().ipAddress("127.0.0.1").nodeId(Peer.randomId()).build()); diff --git a/ethereum/permissioning/src/main/java/tech/pegasys/pantheon/ethereum/permissioning/NodeLocalConfigPermissioningController.java b/ethereum/permissioning/src/main/java/tech/pegasys/pantheon/ethereum/permissioning/NodeLocalConfigPermissioningController.java index d84310f34d..ca5582d792 100644 --- a/ethereum/permissioning/src/main/java/tech/pegasys/pantheon/ethereum/permissioning/NodeLocalConfigPermissioningController.java +++ b/ethereum/permissioning/src/main/java/tech/pegasys/pantheon/ethereum/permissioning/NodeLocalConfigPermissioningController.java @@ -15,6 +15,7 @@ import tech.pegasys.pantheon.ethereum.permissioning.node.NodePermissioningProvider; import tech.pegasys.pantheon.ethereum.permissioning.node.NodeWhitelistUpdatedEvent; import tech.pegasys.pantheon.util.Subscribers; +import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.enode.EnodeURL; import java.io.IOException; @@ -24,6 +25,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; import java.util.stream.Collectors; @@ -38,7 +40,7 @@ public class NodeLocalConfigPermissioningController implements NodePermissioning private LocalPermissioningConfiguration configuration; private final List fixedNodes; - private final EnodeURL selfEnode; + private final BytesValue localNodeId; private final List nodesWhitelist = new ArrayList<>(); private final WhitelistPersistor whitelistPersistor; private final Subscribers> nodeWhitelistUpdatedObservers = @@ -47,22 +49,22 @@ public class NodeLocalConfigPermissioningController implements NodePermissioning public NodeLocalConfigPermissioningController( final LocalPermissioningConfiguration permissioningConfiguration, final List fixedNodes, - final EnodeURL selfEnode) { + final BytesValue localNodeId) { this( permissioningConfiguration, fixedNodes, - selfEnode, + localNodeId, new WhitelistPersistor(permissioningConfiguration.getNodePermissioningConfigFilePath())); } public NodeLocalConfigPermissioningController( final LocalPermissioningConfiguration configuration, final List fixedNodes, - final EnodeURL selfEnode, + final BytesValue localNodeId, final WhitelistPersistor whitelistPersistor) { this.configuration = configuration; this.fixedNodes = fixedNodes; - this.selfEnode = selfEnode; + this.localNodeId = localNodeId; this.whitelistPersistor = whitelistPersistor; readNodesFromConfig(configuration); } @@ -197,10 +199,6 @@ private Collection peerToEnodeURI(final Collection peers) { return peers.parallelStream().map(EnodeURL::toString).collect(Collectors.toList()); } - private boolean checkSelfEnode(final EnodeURL node) { - return selfEnode.getNodeId().equals(node.getNodeId()); - } - private boolean compareEnodes(final EnodeURL nodeA, final EnodeURL nodeB) { boolean idsMatch = nodeA.getNodeId().equals(nodeB.getNodeId()); boolean hostsMatch = nodeA.getIp().equals(nodeB.getIp()); @@ -219,7 +217,7 @@ public boolean isPermitted(final String enodeURL) { } public boolean isPermitted(final EnodeURL node) { - if (checkSelfEnode(node)) { + if (Objects.equals(localNodeId, node.getNodeId())) { return true; } return nodesWhitelist.stream().anyMatch(p -> compareEnodes(p, node)); diff --git a/ethereum/permissioning/src/main/java/tech/pegasys/pantheon/ethereum/permissioning/NodePermissioningControllerFactory.java b/ethereum/permissioning/src/main/java/tech/pegasys/pantheon/ethereum/permissioning/NodePermissioningControllerFactory.java index 16b70b8551..e1506e3e38 100644 --- a/ethereum/permissioning/src/main/java/tech/pegasys/pantheon/ethereum/permissioning/NodePermissioningControllerFactory.java +++ b/ethereum/permissioning/src/main/java/tech/pegasys/pantheon/ethereum/permissioning/NodePermissioningControllerFactory.java @@ -17,6 +17,7 @@ import tech.pegasys.pantheon.ethereum.permissioning.node.NodePermissioningProvider; import tech.pegasys.pantheon.ethereum.permissioning.node.provider.SyncStatusNodePermissioningProvider; import tech.pegasys.pantheon.ethereum.transaction.TransactionSimulator; +import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.enode.EnodeURL; import java.util.ArrayList; @@ -30,7 +31,7 @@ public NodePermissioningController create( final PermissioningConfiguration permissioningConfiguration, final Synchronizer synchronizer, final Collection fixedNodes, - final EnodeURL selfEnode, + final BytesValue localNodeId, final TransactionSimulator transactionSimulator) { Optional syncStatusProviderOptional; @@ -42,7 +43,7 @@ public NodePermissioningController create( if (localPermissioningConfiguration.isNodeWhitelistEnabled()) { NodeLocalConfigPermissioningController localProvider = new NodeLocalConfigPermissioningController( - localPermissioningConfiguration, new ArrayList<>(fixedNodes), selfEnode); + localPermissioningConfiguration, new ArrayList<>(fixedNodes), localNodeId); providers.add(localProvider); } } diff --git a/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeLocalConfigPermissioningControllerTest.java b/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeLocalConfigPermissioningControllerTest.java index d621dcf856..f628687780 100644 --- a/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeLocalConfigPermissioningControllerTest.java +++ b/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeLocalConfigPermissioningControllerTest.java @@ -58,8 +58,9 @@ public class NodeLocalConfigPermissioningControllerTest { "enode://6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.10:4567"; private final String enode2 = "enode://5f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.10:4567"; - private final String selfEnode = - "enode://5f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.10:1111"; + private final EnodeURL selfEnode = + EnodeURL.fromString( + "enode://5f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@192.168.0.10:1111"); @Before public void setUp() { @@ -68,7 +69,7 @@ public void setUp() { new NodeLocalConfigPermissioningController( LocalPermissioningConfiguration.createDefault(), bootnodesList, - EnodeURL.fromString(selfEnode), + selfEnode.getNodeId(), whitelistPersistor); } @@ -219,10 +220,8 @@ public void whenCheckingIfNodeIsPermittedDiscoveryPortShouldBeConsideredIfPresen @Test public void whenCheckingIfNodeIsPermittedOrderDoesNotMatter() { controller.addNodes(Arrays.asList(enode1)); - assertThat(controller.isPermitted(EnodeURL.fromString(enode1), EnodeURL.fromString(selfEnode))) - .isTrue(); - assertThat(controller.isPermitted(EnodeURL.fromString(selfEnode), EnodeURL.fromString(enode1))) - .isTrue(); + assertThat(controller.isPermitted(EnodeURL.fromString(enode1), selfEnode)).isTrue(); + assertThat(controller.isPermitted(selfEnode, EnodeURL.fromString(enode1))).isTrue(); } @Test @@ -262,7 +261,7 @@ public void reloadNodeWhitelistWithValidConfigFileShouldUpdateWhitelist() throws .thenReturn(Arrays.asList(URI.create(expectedEnodeURL))); controller = new NodeLocalConfigPermissioningController( - permissioningConfig, bootnodesList, EnodeURL.fromString(selfEnode)); + permissioningConfig, bootnodesList, selfEnode.getNodeId()); controller.reload(); @@ -282,7 +281,7 @@ public void reloadNodeWhitelistWithErrorReadingConfigFileShouldKeepOldWhitelist( .thenReturn(Arrays.asList(URI.create(expectedEnodeURI))); controller = new NodeLocalConfigPermissioningController( - permissioningConfig, bootnodesList, EnodeURL.fromString(selfEnode)); + permissioningConfig, bootnodesList, selfEnode.getNodeId()); final Throwable thrown = catchThrowable(() -> controller.reload()); @@ -381,7 +380,7 @@ public void whenReloadingWhitelistShouldNotifyWhitelistModifiedSubscribers() thr when(permissioningConfig.getNodeWhitelist()).thenReturn(Arrays.asList(URI.create(enode1))); controller = new NodeLocalConfigPermissioningController( - permissioningConfig, bootnodesList, EnodeURL.fromString(selfEnode)); + permissioningConfig, bootnodesList, selfEnode.getNodeId()); controller.subscribeToListUpdatedEvent(consumer); controller.reload(); @@ -404,7 +403,7 @@ public void whenReloadingWhitelistAndNothingChangesShouldNotNotifyWhitelistModif when(permissioningConfig.getNodeWhitelist()).thenReturn(Arrays.asList(URI.create(enode1))); controller = new NodeLocalConfigPermissioningController( - permissioningConfig, bootnodesList, EnodeURL.fromString(selfEnode)); + permissioningConfig, bootnodesList, selfEnode.getNodeId()); controller.subscribeToListUpdatedEvent(consumer); controller.reload(); diff --git a/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/node/NodePermissioningControllerFactoryTest.java b/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/node/NodePermissioningControllerFactoryTest.java index ea27cd2b30..770b0dcf46 100644 --- a/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/node/NodePermissioningControllerFactoryTest.java +++ b/ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/node/NodePermissioningControllerFactoryTest.java @@ -54,7 +54,8 @@ public void testCreateWithNeitherPermissioningEnabled() { config = new PermissioningConfiguration(Optional.empty(), Optional.empty()); NodePermissioningControllerFactory factory = new NodePermissioningControllerFactory(); NodePermissioningController controller = - factory.create(config, synchronizer, bootnodes, selfEnode, transactionSimulator); + factory.create( + config, synchronizer, bootnodes, selfEnode.getNodeId(), transactionSimulator); List providers = controller.getProviders(); assertThat(providers.size()).isEqualTo(0); @@ -73,7 +74,8 @@ public void testCreateWithSmartContractNodePermissioningEnabledOnly() { NodePermissioningControllerFactory factory = new NodePermissioningControllerFactory(); NodePermissioningController controller = - factory.create(config, synchronizer, bootnodes, selfEnode, transactionSimulator); + factory.create( + config, synchronizer, bootnodes, selfEnode.getNodeId(), transactionSimulator); List providers = controller.getProviders(); assertThat(providers.size()).isEqualTo(1); @@ -93,7 +95,8 @@ public void testCreateWithLocalNodePermissioningEnabledOnly() { NodePermissioningControllerFactory factory = new NodePermissioningControllerFactory(); NodePermissioningController controller = - factory.create(config, synchronizer, bootnodes, selfEnode, transactionSimulator); + factory.create( + config, synchronizer, bootnodes, selfEnode.getNodeId(), transactionSimulator); List providers = controller.getProviders(); assertThat(providers.size()).isEqualTo(1); @@ -120,7 +123,8 @@ public void testCreateWithLocalNodeAndSmartContractPermissioningEnabled() { NodePermissioningControllerFactory factory = new NodePermissioningControllerFactory(); NodePermissioningController controller = - factory.create(config, synchronizer, bootnodes, selfEnode, transactionSimulator); + factory.create( + config, synchronizer, bootnodes, selfEnode.getNodeId(), transactionSimulator); List providers = controller.getProviders(); assertThat(providers.size()).isEqualTo(2); diff --git a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java index d4661c5ad4..eb0de4def9 100644 --- a/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java +++ b/pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java @@ -41,7 +41,6 @@ import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.subscription.pending.PendingTransactionSubscriptionService; import tech.pegasys.pantheon.ethereum.jsonrpc.websocket.subscription.syncing.SyncingSubscriptionService; import tech.pegasys.pantheon.ethereum.mainnet.ProtocolSchedule; -import tech.pegasys.pantheon.ethereum.p2p.ConnectingToLocalNodeException; import tech.pegasys.pantheon.ethereum.p2p.InsufficientPeersPermissioningProvider; import tech.pegasys.pantheon.ethereum.p2p.NetworkRunner; import tech.pegasys.pantheon.ethereum.p2p.NetworkRunner.NetworkBuilder; @@ -54,7 +53,6 @@ import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration; import tech.pegasys.pantheon.ethereum.p2p.network.DefaultP2PNetwork; import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer; -import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.wire.Capability; import tech.pegasys.pantheon.ethereum.p2p.wire.SubProtocol; @@ -106,15 +104,6 @@ public class RunnerBuilder { private Optional permissioningConfiguration = Optional.empty(); private Collection staticNodes = Collections.emptyList(); - private EnodeURL getSelfEnode() { - BytesValue nodeId = pantheonController.getLocalNodeKeyPair().getPublicKey().getEncodedBytes(); - return EnodeURL.builder() - .nodeId(nodeId) - .ipAddress(p2pAdvertisedHost) - .listeningPort(p2pListenPort) - .build(); - } - public RunnerBuilder vertx(final Vertx vertx) { this.vertx = vertx; return this; @@ -257,8 +246,10 @@ public Runner build() { new TransactionSimulator( context.getBlockchain(), context.getWorldStateArchive(), protocolSchedule); + BytesValue localNodeId = keyPair.getPublicKey().getEncodedBytes(); final Optional nodePermissioningController = - buildNodePermissioningController(bootnodesAsEnodeURLs, synchronizer, transactionSimulator); + buildNodePermissioningController( + bootnodesAsEnodeURLs, synchronizer, transactionSimulator, localNodeId); final Optional nodeWhitelistController = nodePermissioningController @@ -292,11 +283,12 @@ public Runner build() { .metricsSystem(metricsSystem) .build(); + final P2PNetwork network = networkRunner.getNetwork(); nodePermissioningController.ifPresent( n -> n.setInsufficientPeersPermissioningProvider( new InsufficientPeersPermissioningProvider( - networkRunner.getNetwork(), getSelfEnode(), bootnodesAsEnodeURLs))); + networkRunner.getNetwork(), network::getLocalEnode, bootnodesAsEnodeURLs))); final TransactionPool transactionPool = pantheonController.getTransactionPool(); final MiningCoordinator miningCoordinator = pantheonController.getMiningCoordinator(); @@ -316,14 +308,9 @@ public Runner build() { final P2PNetwork peerNetwork = networkRunner.getNetwork(); - staticNodes.forEach( - enodeURL -> { - final Peer peer = DefaultPeer.fromEnodeURL(enodeURL); - try { - peerNetwork.addMaintainConnectionPeer(peer); - } catch (ConnectingToLocalNodeException ex) { - } - }); + staticNodes.stream() + .map(DefaultPeer::fromEnodeURL) + .forEach(peerNetwork::addMaintainConnectionPeer); Optional jsonRpcHttpService = Optional.empty(); if (jsonRpcConfiguration.isEnabled()) { @@ -409,12 +396,13 @@ public Runner build() { private Optional buildNodePermissioningController( final List bootnodesAsEnodeURLs, final Synchronizer synchronizer, - final TransactionSimulator transactionSimulator) { + final TransactionSimulator transactionSimulator, + final BytesValue localNodeId) { Collection fixedNodes = getFixedNodes(bootnodesAsEnodeURLs, staticNodes); return permissioningConfiguration.map( config -> new NodePermissioningControllerFactory() - .create(config, synchronizer, fixedNodes, getSelfEnode(), transactionSimulator)); + .create(config, synchronizer, fixedNodes, localNodeId, transactionSimulator)); } @VisibleForTesting