Moving NodeWhitelistController to permissioning package (#855)

* Moving NodeWhitelistController to permissioning package

* Refactoring unit tests

* Fix string.format

Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
pull/2/head
Lucas Saldanha 6 years ago committed by GitHub
parent 1dfe3e8eb7
commit d3b9211b82
  1. 7
      acceptance-tests/src/test/java/tech/pegasys/pantheon/tests/acceptance/dsl/node/PantheonNode.java
  2. 21
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/permissioning/PermAddNodesToWhitelist.java
  3. 6
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/permissioning/PermGetNodesWhitelist.java
  4. 2
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/permissioning/PermReloadPermissionsFromFile.java
  5. 21
      ethereum/jsonrpc/src/main/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/permissioning/PermRemoveNodesFromWhitelist.java
  6. 20
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/permissioning/PermAddNodesToWhitelistTest.java
  7. 10
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/permissioning/PermGetNodesWhitelistTest.java
  8. 2
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/permissioning/PermReloadPermissionsFromFileTest.java
  9. 14
      ethereum/jsonrpc/src/test/java/tech/pegasys/pantheon/ethereum/jsonrpc/internal/methods/permissioning/PermRemoveNodesFromWhitelistTest.java
  10. 2
      ethereum/mock-p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/testing/MockNetwork.java
  11. 2
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/NoopP2PNetwork.java
  12. 2
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/api/P2PNetwork.java
  13. 2
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryAgent.java
  14. 2
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/VertxPeerDiscoveryAgent.java
  15. 4
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryController.java
  16. 6
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/RecursivePeerRefreshState.java
  17. 5
      ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/netty/NettyP2PNetwork.java
  18. 18
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/NettyP2PNetworkTest.java
  19. 2
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/PeerDiscoveryTestHelper.java
  20. 2
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/MockPeerDiscoveryAgent.java
  21. 6
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/PeerDiscoveryControllerTest.java
  22. 5
      ethereum/p2p/src/test/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/RecursivePeerRefreshStateTest.java
  23. 116
      ethereum/permissioning/src/main/java/tech/pegasys/pantheon/ethereum/permissioning/NodeWhitelistController.java
  24. 147
      ethereum/permissioning/src/test/java/tech/pegasys/pantheon/ethereum/permissioning/NodeWhitelistControllerTest.java
  25. 2
      pantheon/src/main/java/tech/pegasys/pantheon/RunnerBuilder.java
  26. 21
      util/src/main/java/tech/pegasys/pantheon/util/enode/EnodeURL.java

@ -138,7 +138,12 @@ public class PantheonNode implements Node, NodeConfiguration, RunnableNode, Auto
@Override @Override
public String enodeUrl() { public String enodeUrl() {
return "enode://" + keyPair.getPublicKey().toString() + "@" + LOCALHOST + ":" + p2pPort; return "enode://"
+ keyPair.getPublicKey().toString().substring(2)
+ "@"
+ LOCALHOST
+ ":"
+ p2pPort;
} }
private Optional<String> jsonRpcBaseUrl() { private Optional<String> jsonRpcBaseUrl() {

@ -22,12 +22,9 @@ 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.peers.DefaultPeer; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class PermAddNodesToWhitelist implements JsonRpcMethod { public class PermAddNodesToWhitelist implements JsonRpcMethod {
@ -52,15 +49,9 @@ public class PermAddNodesToWhitelist implements JsonRpcMethod {
try { try {
if (p2pNetwork.getNodeWhitelistController().isPresent()) { if (p2pNetwork.getNodeWhitelistController().isPresent()) {
try { try {
List<Peer> peers = final List<String> enodeURLs = enodeListParam.getStringList();
enodeListParam final NodeWhitelistController.NodesWhitelistResult nodesWhitelistResult =
.getStringList() p2pNetwork.getNodeWhitelistController().get().addNodes(enodeURLs);
.parallelStream()
.map(this::parsePeer)
.collect(Collectors.toList());
NodeWhitelistController.NodesWhitelistResult nodesWhitelistResult =
p2pNetwork.getNodeWhitelistController().get().addNodes(peers);
switch (nodesWhitelistResult.result()) { switch (nodesWhitelistResult.result()) {
case SUCCESS: case SUCCESS:
@ -92,8 +83,4 @@ public class PermAddNodesToWhitelist implements JsonRpcMethod {
return new JsonRpcErrorResponse(req.getId(), JsonRpcError.P2P_DISABLED); return new JsonRpcErrorResponse(req.getId(), JsonRpcError.P2P_DISABLED);
} }
} }
private DefaultPeer parsePeer(final String enodeURI) {
return DefaultPeer.fromURI(enodeURI);
}
} }

@ -20,10 +20,8 @@ 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.peers.Peer;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class PermGetNodesWhitelist implements JsonRpcMethod { public class PermGetNodesWhitelist implements JsonRpcMethod {
@ -42,10 +40,8 @@ public class PermGetNodesWhitelist implements JsonRpcMethod {
public JsonRpcResponse response(final JsonRpcRequest req) { public JsonRpcResponse response(final JsonRpcRequest req) {
try { try {
if (p2pNetwork.getNodeWhitelistController().isPresent()) { if (p2pNetwork.getNodeWhitelistController().isPresent()) {
List<Peer> nodesWhitelist = final List<String> enodeList =
p2pNetwork.getNodeWhitelistController().get().getNodesWhitelist(); p2pNetwork.getNodeWhitelistController().get().getNodesWhitelist();
List<String> enodeList =
nodesWhitelist.parallelStream().map(Peer::getEnodeURI).collect(Collectors.toList());
return new JsonRpcSuccessResponse(req.getId(), enodeList); return new JsonRpcSuccessResponse(req.getId(), enodeList);
} else { } else {

@ -18,8 +18,8 @@ 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.JsonRpcErrorResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse; 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.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.AccountWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.AccountWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import java.util.Optional; import java.util.Optional;

@ -22,12 +22,9 @@ 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.peers.DefaultPeer; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
public class PermRemoveNodesFromWhitelist implements JsonRpcMethod { public class PermRemoveNodesFromWhitelist implements JsonRpcMethod {
@ -52,15 +49,9 @@ public class PermRemoveNodesFromWhitelist implements JsonRpcMethod {
try { try {
if (p2pNetwork.getNodeWhitelistController().isPresent()) { if (p2pNetwork.getNodeWhitelistController().isPresent()) {
try { try {
List<Peer> peers = final List<String> enodeURLs = enodeListParam.getStringList();
enodeListParam final NodeWhitelistController.NodesWhitelistResult nodesWhitelistResult =
.getStringList() p2pNetwork.getNodeWhitelistController().get().removeNodes(enodeURLs);
.parallelStream()
.map(this::parsePeer)
.collect(Collectors.toList());
NodeWhitelistController.NodesWhitelistResult nodesWhitelistResult =
p2pNetwork.getNodeWhitelistController().get().removeNodes(peers);
switch (nodesWhitelistResult.result()) { switch (nodesWhitelistResult.result()) {
case SUCCESS: case SUCCESS:
@ -92,8 +83,4 @@ public class PermRemoveNodesFromWhitelist implements JsonRpcMethod {
return new JsonRpcErrorResponse(req.getId(), JsonRpcError.P2P_DISABLED); return new JsonRpcErrorResponse(req.getId(), JsonRpcError.P2P_DISABLED);
} }
} }
private DefaultPeer parsePeer(final String enodeURI) {
return DefaultPeer.fromURI(enodeURI);
}
} }

@ -19,7 +19,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController.NodesWhitelistResult; import static tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController.NodesWhitelistResult;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter;
@ -29,7 +29,7 @@ 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.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.WhitelistOperationResult; import tech.pegasys.pantheon.ethereum.permissioning.WhitelistOperationResult;
import java.util.ArrayList; import java.util.ArrayList;
@ -74,11 +74,13 @@ public class PermAddNodesToWhitelistTest {
@Test @Test
public void shouldThrowInvalidJsonRpcParametersExceptionWhenOnlyBadEnode() { public void shouldThrowInvalidJsonRpcParametersExceptionWhenOnlyBadEnode() {
final JsonRpcRequest request = buildRequest(Lists.newArrayList(badEnode)); final ArrayList<String> enodeList = Lists.newArrayList(badEnode);
final JsonRpcRequest request = buildRequest(enodeList);
final JsonRpcResponse expected = final JsonRpcResponse expected =
new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_INVALID_ENTRY); new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_INVALID_ENTRY);
when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController)); when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController));
when(nodeWhitelistController.addNodes(eq(enodeList))).thenThrow(IllegalArgumentException.class);
final JsonRpcResponse actual = method.response(request); final JsonRpcResponse actual = method.response(request);
@ -87,11 +89,13 @@ public class PermAddNodesToWhitelistTest {
@Test @Test
public void shouldThrowInvalidJsonRpcParametersExceptionWhenBadEnodeInList() { public void shouldThrowInvalidJsonRpcParametersExceptionWhenBadEnodeInList() {
final JsonRpcRequest request = buildRequest(Lists.newArrayList(enode2, badEnode, enode1)); final ArrayList<String> enodeList = Lists.newArrayList(enode2, badEnode, enode1);
final JsonRpcRequest request = buildRequest(enodeList);
final JsonRpcResponse expected = final JsonRpcResponse expected =
new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_INVALID_ENTRY); new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_INVALID_ENTRY);
when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController)); when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController));
when(nodeWhitelistController.addNodes(eq(enodeList))).thenThrow(IllegalArgumentException.class);
final JsonRpcResponse actual = method.response(request); final JsonRpcResponse actual = method.response(request);
@ -99,12 +103,14 @@ public class PermAddNodesToWhitelistTest {
} }
@Test @Test
public void shouldThrowInvalidJsonRpcParametersExceptionWhenNoEnode() { public void shouldThrowInvalidJsonRpcParametersExceptionWhenEmptyEnode() {
final JsonRpcRequest request = buildRequest(Lists.newArrayList("")); final JsonRpcRequest request = buildRequest(Lists.emptyList());
final JsonRpcResponse expected = final JsonRpcResponse expected =
new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_INVALID_ENTRY); new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_EMPTY_ENTRY);
when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController)); when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController));
when(nodeWhitelistController.addNodes(eq(Lists.emptyList())))
.thenReturn(new NodesWhitelistResult(WhitelistOperationResult.ERROR_EMPTY_ENTRY));
final JsonRpcResponse actual = method.response(request); final JsonRpcResponse actual = method.response(request);

@ -25,14 +25,10 @@ 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.peers.DefaultPeer; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors;
import org.assertj.core.util.Lists; import org.assertj.core.util.Lists;
import org.junit.Before; import org.junit.Before;
@ -118,7 +114,7 @@ public class PermGetNodesWhitelistTest {
return new JsonRpcRequest("2.0", METHOD_NAME, new Object[] {}); return new JsonRpcRequest("2.0", METHOD_NAME, new Object[] {});
} }
private List<Peer> buildNodesList(final String... enodes) { private List<String> buildNodesList(final String... enodes) {
return Arrays.stream(enodes).parallel().map(DefaultPeer::fromURI).collect(Collectors.toList()); return Lists.newArrayList(enodes);
} }
} }

@ -21,8 +21,8 @@ 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.JsonRpcErrorResponse;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.response.JsonRpcResponse; 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.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.AccountWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.AccountWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import java.util.Optional; import java.util.Optional;

@ -19,7 +19,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController.NodesWhitelistResult; import static tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController.NodesWhitelistResult;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.JsonRpcRequest;
import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter; import tech.pegasys.pantheon.ethereum.jsonrpc.internal.parameters.JsonRpcParameter;
@ -29,7 +29,7 @@ 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.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.WhitelistOperationResult; import tech.pegasys.pantheon.ethereum.permissioning.WhitelistOperationResult;
import java.util.ArrayList; import java.util.ArrayList;
@ -79,6 +79,8 @@ public class PermRemoveNodesFromWhitelistTest {
new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_INVALID_ENTRY); new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_INVALID_ENTRY);
when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController)); when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController));
when(nodeWhitelistController.removeNodes(eq(Lists.newArrayList(badEnode))))
.thenThrow(IllegalArgumentException.class);
final JsonRpcResponse actual = method.response(request); final JsonRpcResponse actual = method.response(request);
@ -86,12 +88,14 @@ public class PermRemoveNodesFromWhitelistTest {
} }
@Test @Test
public void shouldThrowInvalidJsonRpcParametersExceptionWhenNoEnode() { public void shouldThrowInvalidJsonRpcParametersExceptionWhenEmptyList() {
final JsonRpcRequest request = buildRequest(Lists.newArrayList("")); final JsonRpcRequest request = buildRequest(Lists.emptyList());
final JsonRpcResponse expected = final JsonRpcResponse expected =
new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_INVALID_ENTRY); new JsonRpcErrorResponse(request.getId(), JsonRpcError.NODE_WHITELIST_EMPTY_ENTRY);
when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController)); when(p2pNetwork.getNodeWhitelistController()).thenReturn(Optional.of(nodeWhitelistController));
when(nodeWhitelistController.removeNodes(eq(Lists.emptyList())))
.thenReturn(new NodesWhitelistResult(WhitelistOperationResult.ERROR_EMPTY_ENTRY));
final JsonRpcResponse actual = method.response(request); final JsonRpcResponse actual = method.response(request);

@ -18,11 +18,11 @@ 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.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController;
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;
import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo; import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.DisconnectReason; import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.DisconnectReason;
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.InetSocketAddress;

@ -17,9 +17,9 @@ import tech.pegasys.pantheon.ethereum.p2p.api.Message;
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.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.p2p.wire.Capability; import tech.pegasys.pantheon.ethereum.p2p.wire.Capability;
import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo; import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;

@ -13,9 +13,9 @@
package tech.pegasys.pantheon.ethereum.p2p.api; package tech.pegasys.pantheon.ethereum.p2p.api;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.p2p.wire.Capability; import tech.pegasys.pantheon.ethereum.p2p.wire.Capability;
import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo; import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import java.io.Closeable; import java.io.Closeable;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;

@ -32,8 +32,8 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.TimerUtil;
import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeerId; import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeerId;
import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint; import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage; import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.util.NetworkUtility; import tech.pegasys.pantheon.util.NetworkUtility;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;

@ -23,7 +23,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.TimerUtil;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.VertxTimerUtil; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.VertxTimerUtil;
import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint; import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.util.NetworkUtility; import tech.pegasys.pantheon.util.NetworkUtility;
import tech.pegasys.pantheon.util.Preconditions; import tech.pegasys.pantheon.util.Preconditions;

@ -24,7 +24,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryEvent.PeerBonde
import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryStatus; import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryStatus;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
@ -201,7 +201,7 @@ public class PeerDiscoveryController {
private boolean whitelistIfPresentIsNodePermitted(final DiscoveryPeer sender) { private boolean whitelistIfPresentIsNodePermitted(final DiscoveryPeer sender) {
return nodeWhitelistController return nodeWhitelistController
.map(nodeWhitelistController -> nodeWhitelistController.isPermitted(sender)) .map(nodeWhitelistController -> nodeWhitelistController.isPermitted(sender.getEnodeURI()))
.orElse(true); .orElse(true);
} }

@ -17,7 +17,7 @@ import static tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PeerDistance
import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer; import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer;
import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryStatus; import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryStatus;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.List; import java.util.List;
@ -183,7 +183,9 @@ public class RecursivePeerRefreshState {
private boolean satisfiesMapAdditionCriteria(final DiscoveryPeer discoPeer) { private boolean satisfiesMapAdditionCriteria(final DiscoveryPeer discoPeer) {
return !oneTrueMap.containsKey(discoPeer.getId()) return !oneTrueMap.containsKey(discoPeer.getId())
&& !peerBlacklist.contains(discoPeer) && !peerBlacklist.contains(discoPeer)
&& peerWhitelist.map(whitelist -> whitelist.isPermitted(discoPeer)).orElse(true) && peerWhitelist
.map(whitelist -> whitelist.isPermitted(discoPeer.getEnodeURI()))
.orElse(true)
&& (initialPeers.contains(discoPeer) || !peerTable.get(discoPeer).isPresent()) && (initialPeers.contains(discoPeer) || !peerTable.get(discoPeer).isPresent())
&& !discoPeer.getId().equals(localPeerId); && !discoPeer.getId().equals(localPeerId);
} }

@ -28,11 +28,11 @@ import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer;
import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint; import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.p2p.wire.Capability; import tech.pegasys.pantheon.ethereum.p2p.wire.Capability;
import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo; import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.ethereum.p2p.wire.SubProtocol; import tech.pegasys.pantheon.ethereum.p2p.wire.SubProtocol;
import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.DisconnectReason; import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.DisconnectReason;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.metrics.Counter; import tech.pegasys.pantheon.metrics.Counter;
import tech.pegasys.pantheon.metrics.LabelledMetric; import tech.pegasys.pantheon.metrics.LabelledMetric;
import tech.pegasys.pantheon.metrics.MetricCategory; import tech.pegasys.pantheon.metrics.MetricCategory;
@ -307,7 +307,8 @@ public class NettyP2PNetwork implements P2PNetwork {
connection.getPeer().getNodeId(), connection.getPeer().getNodeId(),
ch.remoteAddress().getAddress().getHostAddress(), ch.remoteAddress().getAddress().getHostAddress(),
connection.getPeer().getPort(), connection.getPeer().getPort(),
connection.getPeer().getPort()))) connection.getPeer().getPort())
.getEnodeURI()))
.orElse(true); .orElse(true);
} }

@ -35,17 +35,18 @@ import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer;
import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint; import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.p2p.wire.Capability; import tech.pegasys.pantheon.ethereum.p2p.wire.Capability;
import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo; import tech.pegasys.pantheon.ethereum.p2p.wire.PeerInfo;
import tech.pegasys.pantheon.ethereum.p2p.wire.SubProtocol; import tech.pegasys.pantheon.ethereum.p2p.wire.SubProtocol;
import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.DisconnectReason; import tech.pegasys.pantheon.ethereum.p2p.wire.messages.DisconnectMessage.DisconnectReason;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration; import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem; import tech.pegasys.pantheon.metrics.noop.NoOpMetricsSystem;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.net.InetAddress; import java.net.InetAddress;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.OptionalInt; import java.util.OptionalInt;
@ -416,7 +417,7 @@ public final class NettyP2PNetworkTest {
Files.createTempFile("test", "test").toAbsolutePath().toString()); Files.createTempFile("test", "test").toAbsolutePath().toString());
final NodeWhitelistController localWhitelistController = new NodeWhitelistController(config); final NodeWhitelistController localWhitelistController = new NodeWhitelistController(config);
// turn on whitelisting by adding a different node NOT remote node // turn on whitelisting by adding a different node NOT remote node
localWhitelistController.addNode(mockPeer()); localWhitelistController.addNodes(Arrays.asList(mockPeer().getEnodeURI()));
final SubProtocol subprotocol = subProtocol(); final SubProtocol subprotocol = subProtocol();
final Capability cap = Capability.create(subprotocol.getName(), 63); final Capability cap = Capability.create(subprotocol.getName(), 63);
@ -646,8 +647,19 @@ public final class NettyP2PNetworkTest {
private Peer mockPeer() { private Peer mockPeer() {
final Peer peer = mock(Peer.class); final Peer peer = mock(Peer.class);
final BytesValue id = SECP256K1.KeyPair.generate().getPublicKey().getEncodedBytes(); final BytesValue id = SECP256K1.KeyPair.generate().getPublicKey().getEncodedBytes();
final Endpoint endpoint = new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303));
final String enodeURL =
String.format(
"enode://%s@%s:%d?discport=%d",
id.toString().substring(2),
endpoint.getHost(),
endpoint.getUdpPort(),
endpoint.getTcpPort().getAsInt());
when(peer.getId()).thenReturn(id); when(peer.getId()).thenReturn(id);
when(peer.getEndpoint()).thenReturn(new Endpoint("127.0.0.1", 30303, OptionalInt.of(30303))); when(peer.getEndpoint()).thenReturn(endpoint);
when(peer.getEnodeURI()).thenReturn(enodeURL);
return peer; return peer;
} }
} }

@ -20,7 +20,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.Packet;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PacketType; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PacketType;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PingPacketData; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.PingPacketData;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.util.Arrays; import java.util.Arrays;

@ -17,7 +17,7 @@ import tech.pegasys.pantheon.ethereum.p2p.config.DiscoveryConfiguration;
import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer; import tech.pegasys.pantheon.ethereum.p2p.discovery.DiscoveryPeer;
import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryAgent; import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryAgent;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;

@ -35,7 +35,7 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryTestHelper;
import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint; import tech.pegasys.pantheon.ethereum.p2p.peers.Endpoint;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer; import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration; import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.util.Subscribers; import tech.pegasys.pantheon.util.Subscribers;
import tech.pegasys.pantheon.util.bytes.Bytes32; import tech.pegasys.pantheon.util.bytes.Bytes32;
@ -947,8 +947,8 @@ public class PeerDiscoveryControllerTest {
final NodeWhitelistController nodeWhitelistController = new NodeWhitelistController(config); final NodeWhitelistController nodeWhitelistController = new NodeWhitelistController(config);
// Whitelist peers // Whitelist peers
nodeWhitelistController.addNode(discoPeer); nodeWhitelistController.addNodes(Arrays.asList(discoPeer.getEnodeURI()));
nodeWhitelistController.addNode(otherPeer2); nodeWhitelistController.addNodes(Arrays.asList(otherPeer2.getEnodeURI()));
final OutboundMessageHandler outboundMessageHandler = mock(OutboundMessageHandler.class); final OutboundMessageHandler outboundMessageHandler = mock(OutboundMessageHandler.class);
controller = controller =

@ -27,11 +27,12 @@ import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryStatus;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.RecursivePeerRefreshState.BondingAgent; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.RecursivePeerRefreshState.BondingAgent;
import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.RecursivePeerRefreshState.FindNeighbourDispatcher; import tech.pegasys.pantheon.ethereum.p2p.discovery.internal.RecursivePeerRefreshState.FindNeighbourDispatcher;
import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist; import tech.pegasys.pantheon.ethereum.p2p.peers.PeerBlacklist;
import tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration; import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.nio.file.Files; import java.nio.file.Files;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
@ -486,7 +487,7 @@ public class RecursivePeerRefreshStateTest {
final NodeWhitelistController peerWhitelist = final NodeWhitelistController peerWhitelist =
new NodeWhitelistController(permissioningConfiguration); new NodeWhitelistController(permissioningConfiguration);
peerWhitelist.addNode(peerA); peerWhitelist.addNodes(Arrays.asList(peerA.getEnodeURI()));
recursivePeerRefreshState = recursivePeerRefreshState =
new RecursivePeerRefreshState( new RecursivePeerRefreshState(

@ -10,15 +10,9 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 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. * specific language governing permissions and limitations under the License.
*/ */
package tech.pegasys.pantheon.ethereum.p2p.permissioning; package tech.pegasys.pantheon.ethereum.permissioning;
import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer; import tech.pegasys.pantheon.util.enode.EnodeURL;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfigurationBuilder;
import tech.pegasys.pantheon.ethereum.permissioning.WhitelistFileSyncException;
import tech.pegasys.pantheon.ethereum.permissioning.WhitelistOperationResult;
import tech.pegasys.pantheon.ethereum.permissioning.WhitelistPersistor;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -38,7 +32,7 @@ public class NodeWhitelistController {
private static final Logger LOG = LogManager.getLogger(); private static final Logger LOG = LogManager.getLogger();
private PermissioningConfiguration configuration; private PermissioningConfiguration configuration;
private List<Peer> nodesWhitelist = new ArrayList<>(); private List<EnodeURL> nodesWhitelist = new ArrayList<>();
private final WhitelistPersistor whitelistPersistor; private final WhitelistPersistor whitelistPersistor;
public NodeWhitelistController(final PermissioningConfiguration permissioningConfiguration) { public NodeWhitelistController(final PermissioningConfiguration permissioningConfiguration) {
@ -57,70 +51,72 @@ public class NodeWhitelistController {
private void readNodesFromConfig(final PermissioningConfiguration configuration) { private void readNodesFromConfig(final PermissioningConfiguration configuration) {
if (configuration.isNodeWhitelistEnabled() && configuration.getNodeWhitelist() != null) { if (configuration.isNodeWhitelistEnabled() && configuration.getNodeWhitelist() != null) {
for (URI uri : configuration.getNodeWhitelist()) { for (URI uri : configuration.getNodeWhitelist()) {
nodesWhitelist.add(DefaultPeer.fromURI(uri)); nodesWhitelist.add(new EnodeURL(uri.toString()));
} }
} }
} }
public boolean addNode(final Peer node) { public NodesWhitelistResult addNodes(final List<String> enodeURLs) {
return nodesWhitelist.add(node); final NodesWhitelistResult inputValidationResult = validInput(enodeURLs);
}
private boolean removeNode(final Peer node) {
return nodesWhitelist.remove(node);
}
public NodesWhitelistResult addNodes(final List<Peer> peers) {
final NodesWhitelistResult inputValidationResult = validInput(peers);
if (inputValidationResult.result() != WhitelistOperationResult.SUCCESS) { if (inputValidationResult.result() != WhitelistOperationResult.SUCCESS) {
return inputValidationResult; return inputValidationResult;
} }
final List<EnodeURL> peers = enodeURLs.stream().map(EnodeURL::new).collect(Collectors.toList());
for (Peer peer : peers) { for (EnodeURL peer : peers) {
if (nodesWhitelist.contains(peer)) { if (nodesWhitelist.contains(peer)) {
return new NodesWhitelistResult( return new NodesWhitelistResult(
WhitelistOperationResult.ERROR_EXISTING_ENTRY, WhitelistOperationResult.ERROR_EXISTING_ENTRY,
String.format("Specified peer: %s already exists in whitelist.", peer.getId())); String.format("Specified peer: %s already exists in whitelist.", peer.getNodeId()));
} }
} }
final List<Peer> oldWhitelist = new ArrayList<>(this.nodesWhitelist); final List<EnodeURL> oldWhitelist = new ArrayList<>(this.nodesWhitelist);
peers.forEach(this::addNode); peers.forEach(this::addNode);
try {
verifyConfigurationFileState(peerToEnodeURI(oldWhitelist)); final NodesWhitelistResult updateConfigFileResult = updateWhitelistInConfigFile(oldWhitelist);
updateConfigurationFile(peerToEnodeURI(nodesWhitelist)); if (updateConfigFileResult.result() != WhitelistOperationResult.SUCCESS) {
verifyConfigurationFileState(peerToEnodeURI(nodesWhitelist)); return updateConfigFileResult;
} catch (IOException e) {
revertState(oldWhitelist);
return new NodesWhitelistResult(WhitelistOperationResult.ERROR_WHITELIST_PERSIST_FAIL);
} catch (WhitelistFileSyncException e) {
return new NodesWhitelistResult(WhitelistOperationResult.ERROR_WHITELIST_FILE_SYNC);
} }
return new NodesWhitelistResult(WhitelistOperationResult.SUCCESS); return new NodesWhitelistResult(WhitelistOperationResult.SUCCESS);
} }
private boolean peerListHasDuplicates(final List<Peer> peers) { private boolean addNode(final EnodeURL enodeURL) {
return !peers.stream().allMatch(new HashSet<>()::add); return nodesWhitelist.add(enodeURL);
} }
public NodesWhitelistResult removeNodes(final List<Peer> peers) { public NodesWhitelistResult removeNodes(final List<String> enodeURLs) {
final NodesWhitelistResult inputValidationResult = validInput(peers); final NodesWhitelistResult inputValidationResult = validInput(enodeURLs);
if (inputValidationResult.result() != WhitelistOperationResult.SUCCESS) { if (inputValidationResult.result() != WhitelistOperationResult.SUCCESS) {
return inputValidationResult; return inputValidationResult;
} }
final List<EnodeURL> peers = enodeURLs.stream().map(EnodeURL::new).collect(Collectors.toList());
for (Peer peer : peers) { for (EnodeURL peer : peers) {
if (!(nodesWhitelist.contains(peer))) { if (!(nodesWhitelist.contains(peer))) {
return new NodesWhitelistResult( return new NodesWhitelistResult(
WhitelistOperationResult.ERROR_ABSENT_ENTRY, WhitelistOperationResult.ERROR_ABSENT_ENTRY,
String.format("Specified peer: %s does not exist in whitelist.", peer.getId())); String.format("Specified peer: %s does not exist in whitelist.", peer.getNodeId()));
} }
} }
final List<Peer> oldWhitelist = new ArrayList<>(this.nodesWhitelist); final List<EnodeURL> oldWhitelist = new ArrayList<>(this.nodesWhitelist);
peers.forEach(this::removeNode); peers.forEach(this::removeNode);
final NodesWhitelistResult updateConfigFileResult = updateWhitelistInConfigFile(oldWhitelist);
if (updateConfigFileResult.result() != WhitelistOperationResult.SUCCESS) {
return updateConfigFileResult;
}
return new NodesWhitelistResult(WhitelistOperationResult.SUCCESS);
}
private boolean removeNode(final EnodeURL enodeURL) {
return nodesWhitelist.remove(enodeURL);
}
private NodesWhitelistResult updateWhitelistInConfigFile(final List<EnodeURL> oldWhitelist) {
try { try {
verifyConfigurationFileState(peerToEnodeURI(oldWhitelist)); verifyConfigurationFileState(peerToEnodeURI(oldWhitelist));
updateConfigurationFile(peerToEnodeURI(nodesWhitelist)); updateConfigurationFile(peerToEnodeURI(nodesWhitelist));
@ -131,10 +127,11 @@ public class NodeWhitelistController {
} catch (WhitelistFileSyncException e) { } catch (WhitelistFileSyncException e) {
return new NodesWhitelistResult(WhitelistOperationResult.ERROR_WHITELIST_FILE_SYNC); return new NodesWhitelistResult(WhitelistOperationResult.ERROR_WHITELIST_FILE_SYNC);
} }
return new NodesWhitelistResult(WhitelistOperationResult.SUCCESS); return new NodesWhitelistResult(WhitelistOperationResult.SUCCESS);
} }
private NodesWhitelistResult validInput(final List<Peer> peers) { private NodesWhitelistResult validInput(final List<String> peers) {
if (peers == null || peers.isEmpty()) { if (peers == null || peers.isEmpty()) {
return new NodesWhitelistResult( return new NodesWhitelistResult(
WhitelistOperationResult.ERROR_EMPTY_ENTRY, String.format("Null/empty peers list")); WhitelistOperationResult.ERROR_EMPTY_ENTRY, String.format("Null/empty peers list"));
@ -149,6 +146,10 @@ public class NodeWhitelistController {
return new NodesWhitelistResult(WhitelistOperationResult.SUCCESS); return new NodesWhitelistResult(WhitelistOperationResult.SUCCESS);
} }
private boolean peerListHasDuplicates(final List<String> peers) {
return !peers.stream().allMatch(new HashSet<>()::add);
}
private void verifyConfigurationFileState(final Collection<String> oldNodes) private void verifyConfigurationFileState(final Collection<String> oldNodes)
throws IOException, WhitelistFileSyncException { throws IOException, WhitelistFileSyncException {
whitelistPersistor.verifyConfigFileMatchesState( whitelistPersistor.verifyConfigFileMatchesState(
@ -159,40 +160,41 @@ public class NodeWhitelistController {
whitelistPersistor.updateConfig(WhitelistPersistor.WHITELIST_TYPE.NODES, nodes); whitelistPersistor.updateConfig(WhitelistPersistor.WHITELIST_TYPE.NODES, nodes);
} }
private void revertState(final List<Peer> nodesWhitelist) { private void revertState(final List<EnodeURL> nodesWhitelist) {
this.nodesWhitelist = nodesWhitelist; this.nodesWhitelist = nodesWhitelist;
} }
private Collection<String> peerToEnodeURI(final Collection<Peer> peers) { private Collection<String> peerToEnodeURI(final Collection<EnodeURL> peers) {
return peers.parallelStream().map(Peer::getEnodeURI).collect(Collectors.toList()); return peers.parallelStream().map(EnodeURL::toString).collect(Collectors.toList());
}
public boolean isPermitted(final String enodeURL) {
return isPermitted(new EnodeURL(enodeURL));
} }
public boolean isPermitted(final Peer node) { private boolean isPermitted(final EnodeURL node) {
return nodesWhitelist.stream() return nodesWhitelist.stream()
.anyMatch( .anyMatch(
p -> { p -> {
boolean idsMatch = node.getId().equals(p.getId()); boolean idsMatch = node.getNodeId().equals(p.getNodeId());
boolean hostsMatch = node.getEndpoint().getHost().equals(p.getEndpoint().getHost()); boolean hostsMatch = node.getIp().equals(p.getIp());
boolean udpPortsMatch = boolean udpPortsMatch = node.getListeningPort().equals(p.getListeningPort());
node.getEndpoint().getUdpPort() == p.getEndpoint().getUdpPort();
boolean tcpPortsMatchIfPresent = true; boolean tcpPortsMatchIfPresent = true;
if (node.getEndpoint().getTcpPort().isPresent() if (node.getDiscoveryPort().isPresent() && p.getDiscoveryPort().isPresent()) {
&& p.getEndpoint().getTcpPort().isPresent()) {
tcpPortsMatchIfPresent = tcpPortsMatchIfPresent =
node.getEndpoint().getTcpPort().getAsInt() node.getDiscoveryPort().getAsInt() == p.getDiscoveryPort().getAsInt();
== p.getEndpoint().getTcpPort().getAsInt();
} }
return idsMatch && hostsMatch && udpPortsMatch && tcpPortsMatchIfPresent; return idsMatch && hostsMatch && udpPortsMatch && tcpPortsMatchIfPresent;
}); });
} }
public List<Peer> getNodesWhitelist() { public List<String> getNodesWhitelist() {
return nodesWhitelist; return nodesWhitelist.stream().map(Object::toString).collect(Collectors.toList());
} }
public synchronized void reload() throws RuntimeException { public synchronized void reload() throws RuntimeException {
final List<Peer> currentAccountsList = new ArrayList<>(nodesWhitelist); final List<EnodeURL> currentAccountsList = new ArrayList<>(nodesWhitelist);
nodesWhitelist.clear(); nodesWhitelist.clear();
try { try {

@ -10,7 +10,7 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 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. * specific language governing permissions and limitations under the License.
*/ */
package tech.pegasys.pantheon.ethereum.p2p.permissioning; package tech.pegasys.pantheon.ethereum.permissioning;
import static java.util.Collections.singletonList; import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -22,15 +22,9 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import static tech.pegasys.pantheon.ethereum.p2p.permissioning.NodeWhitelistController.NodesWhitelistResult; import static tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController.NodesWhitelistResult;
import tech.pegasys.pantheon.ethereum.p2p.peers.DefaultPeer; import tech.pegasys.pantheon.util.enode.EnodeURL;
import tech.pegasys.pantheon.ethereum.p2p.peers.Peer;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.ethereum.permissioning.WhitelistFileSyncException;
import tech.pegasys.pantheon.ethereum.permissioning.WhitelistOperationResult;
import tech.pegasys.pantheon.ethereum.permissioning.WhitelistPersistor;
import tech.pegasys.pantheon.util.bytes.BytesValue;
import java.io.IOException; import java.io.IOException;
import java.net.URI; import java.net.URI;
@ -67,13 +61,11 @@ public class NodeWhitelistControllerTest {
@Test @Test
public void whenAddNodesInputHasExistingNodeShouldReturnAddErrorExistingEntry() { public void whenAddNodesInputHasExistingNodeShouldReturnAddErrorExistingEntry() {
controller.addNode(DefaultPeer.fromURI(enode1)); controller.addNodes(Arrays.asList(enode1));
NodesWhitelistResult expected = NodesWhitelistResult expected =
new NodesWhitelistResult(WhitelistOperationResult.ERROR_EXISTING_ENTRY); new NodesWhitelistResult(WhitelistOperationResult.ERROR_EXISTING_ENTRY);
NodesWhitelistResult actualResult = NodesWhitelistResult actualResult = controller.addNodes(Lists.newArrayList(enode1, enode2));
controller.addNodes(
Lists.newArrayList(DefaultPeer.fromURI(enode1), DefaultPeer.fromURI(enode2)));
assertThat(actualResult).isEqualToComparingOnlyGivenFields(expected, "result"); assertThat(actualResult).isEqualToComparingOnlyGivenFields(expected, "result");
} }
@ -83,9 +75,7 @@ public class NodeWhitelistControllerTest {
NodesWhitelistResult expected = NodesWhitelistResult expected =
new NodesWhitelistResult(WhitelistOperationResult.ERROR_DUPLICATED_ENTRY); new NodesWhitelistResult(WhitelistOperationResult.ERROR_DUPLICATED_ENTRY);
NodesWhitelistResult actualResult = NodesWhitelistResult actualResult = controller.addNodes(Arrays.asList(enode1, enode1));
controller.addNodes(
Arrays.asList(DefaultPeer.fromURI(enode1), DefaultPeer.fromURI(enode1)));
assertThat(actualResult).isEqualToComparingOnlyGivenFields(expected, "result"); assertThat(actualResult).isEqualToComparingOnlyGivenFields(expected, "result");
} }
@ -112,9 +102,7 @@ public class NodeWhitelistControllerTest {
public void whenRemoveNodesInputHasAbsentNodeShouldReturnRemoveErrorAbsentEntry() { public void whenRemoveNodesInputHasAbsentNodeShouldReturnRemoveErrorAbsentEntry() {
NodesWhitelistResult expected = NodesWhitelistResult expected =
new NodesWhitelistResult(WhitelistOperationResult.ERROR_ABSENT_ENTRY); new NodesWhitelistResult(WhitelistOperationResult.ERROR_ABSENT_ENTRY);
NodesWhitelistResult actualResult = NodesWhitelistResult actualResult = controller.removeNodes(Lists.newArrayList(enode1, enode2));
controller.removeNodes(
Lists.newArrayList(DefaultPeer.fromURI(enode1), DefaultPeer.fromURI(enode2)));
assertThat(actualResult).isEqualToComparingOnlyGivenFields(expected, "result"); assertThat(actualResult).isEqualToComparingOnlyGivenFields(expected, "result");
} }
@ -123,9 +111,7 @@ public class NodeWhitelistControllerTest {
public void whenRemoveNodesInputHasDuplicateNodesShouldReturnErrorDuplicatedEntry() { public void whenRemoveNodesInputHasDuplicateNodesShouldReturnErrorDuplicatedEntry() {
NodesWhitelistResult expected = NodesWhitelistResult expected =
new NodesWhitelistResult(WhitelistOperationResult.ERROR_DUPLICATED_ENTRY); new NodesWhitelistResult(WhitelistOperationResult.ERROR_DUPLICATED_ENTRY);
NodesWhitelistResult actualResult = NodesWhitelistResult actualResult = controller.removeNodes(Lists.newArrayList(enode1, enode1));
controller.removeNodes(
Lists.newArrayList(DefaultPeer.fromURI(enode1), DefaultPeer.fromURI(enode1)));
assertThat(actualResult).isEqualToComparingOnlyGivenFields(expected, "result"); assertThat(actualResult).isEqualToComparingOnlyGivenFields(expected, "result");
} }
@ -150,103 +136,60 @@ public class NodeWhitelistControllerTest {
@Test @Test
public void whenNodeIdsAreDifferentItShouldNotBePermitted() { public void whenNodeIdsAreDifferentItShouldNotBePermitted() {
Peer peer1 = String peer1 =
new DefaultPeer( "enode://aaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.1:30303";
BytesValue.fromHexString( String peer2 =
"0xaaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"), "enode://bbbb80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.1:30303";
"127.0.0.1",
30303); controller.addNodes(Arrays.asList(peer1));
Peer peer2 =
new DefaultPeer(
BytesValue.fromHexString(
"0xbbba80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"),
"127.0.0.1",
30303);
controller.addNode(peer1);
assertThat(controller.isPermitted(peer2)).isFalse(); assertThat(controller.isPermitted(peer2)).isFalse();
} }
@Test @Test
public void whenNodesHostsAreDifferentItShouldNotBePermitted() { public void whenNodesHostsAreDifferentItShouldNotBePermitted() {
Peer peer1 = String peer1 =
new DefaultPeer( "enode://aaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.1:30303";
BytesValue.fromHexString( String peer2 =
"0xaaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"), "enode://aaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.2:30303";
"127.0.0.1",
30303); controller.addNodes(Arrays.asList(peer1));
Peer peer2 =
new DefaultPeer(
BytesValue.fromHexString(
"0xaaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"),
"127.0.0.2",
30303);
controller.addNode(peer1);
assertThat(controller.isPermitted(peer2)).isFalse(); assertThat(controller.isPermitted(peer2)).isFalse();
} }
@Test @Test
public void whenNodesUdpPortsAreDifferentItShouldNotBePermitted() { public void whenNodesUdpPortsAreDifferentItShouldNotBePermitted() {
Peer peer1 = String peer1 =
new DefaultPeer( "enode://aaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.1:30301";
BytesValue.fromHexString( String peer2 =
"0xaaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"), "enode://aaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.1:30302";
"127.0.0.1",
30301); controller.addNodes(Arrays.asList(peer1));
Peer peer2 =
new DefaultPeer(
BytesValue.fromHexString(
"0xaaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"),
"127.0.0.1",
30302);
controller.addNode(peer1);
assertThat(controller.isPermitted(peer2)).isFalse(); assertThat(controller.isPermitted(peer2)).isFalse();
} }
@Test @Test
public void whenCheckingIfNodeIsPermittedTcpPortShouldNotBeConsideredIfAbsent() { public void whenCheckingIfNodeIsPermittedTcpPortShouldNotBeConsideredIfAbsent() {
Peer peerWithTcpPortSet = String peerWithTcpPortSet =
new DefaultPeer( "enode://aaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.1:30303?discport=10001";
BytesValue.fromHexString( String peerWithoutTcpPortSet =
"0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"), "enode://aaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.1:30303";
"127.0.0.1",
30303, controller.addNodes(Arrays.asList(peerWithTcpPortSet));
10001);
Peer peerWithoutTcpPortSet = assertThat(controller.isPermitted(peerWithoutTcpPortSet)).isTrue();
new DefaultPeer(
BytesValue.fromHexString(
"0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"),
"127.0.0.1",
30303);
controller.addNode(peerWithoutTcpPortSet);
assertThat(controller.isPermitted(peerWithTcpPortSet)).isTrue();
} }
@Test @Test
public void whenCheckingIfNodeIsPermittedTcpPortShouldBeConsideredIfPresent() { public void whenCheckingIfNodeIsPermittedTcpPortShouldBeConsideredIfPresent() {
Peer peerWithTcpPortSet = String peerWithTcpPortSet =
new DefaultPeer( "enode://aaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.1:30303?discport=10001";
BytesValue.fromHexString( String peerWithDifferentTcpPortSet =
"0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"), "enode://aaaa80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0@127.0.0.1:30303?discport=10002";
"127.0.0.1",
30303, controller.addNodes(Arrays.asList(peerWithDifferentTcpPortSet));
10001);
Peer peerWithDifferentTcpPortSet =
new DefaultPeer(
BytesValue.fromHexString(
"0x6f8a80d14311c39f35f516fa664deaaaa13e85b2f7493f37f6144d86991ec012937307647bd3b9a82abe2974e1407241d54947bbb39763a4cac9f77166ad92a0"),
"127.0.0.1",
30303,
10002);
controller.addNode(peerWithDifferentTcpPortSet);
assertThat(controller.isPermitted(peerWithTcpPortSet)).isFalse(); assertThat(controller.isPermitted(peerWithTcpPortSet)).isFalse();
} }
@ -254,8 +197,8 @@ public class NodeWhitelistControllerTest {
@Test @Test
public void stateShouldRevertIfWhitelistPersistFails() public void stateShouldRevertIfWhitelistPersistFails()
throws IOException, WhitelistFileSyncException { throws IOException, WhitelistFileSyncException {
List<Peer> newNode1 = singletonList(DefaultPeer.fromURI(enode1)); List<String> newNode1 = singletonList(new EnodeURL(enode1).toString());
List<Peer> newNode2 = singletonList(DefaultPeer.fromURI(enode2)); List<String> newNode2 = singletonList(new EnodeURL(enode2).toString());
assertThat(controller.getNodesWhitelist().size()).isEqualTo(0); assertThat(controller.getNodesWhitelist().size()).isEqualTo(0);
@ -289,8 +232,7 @@ public class NodeWhitelistControllerTest {
controller.reload(); controller.reload();
assertThat(controller.getNodesWhitelist()) assertThat(controller.getNodesWhitelist()).containsExactly(expectedEnodeURL);
.containsExactly(DefaultPeer.fromURI(expectedEnodeURL));
} }
@Test @Test
@ -311,8 +253,7 @@ public class NodeWhitelistControllerTest {
.isInstanceOf(RuntimeException.class) .isInstanceOf(RuntimeException.class)
.hasMessageContaining("Unable to read permissions TOML config file"); .hasMessageContaining("Unable to read permissions TOML config file");
assertThat(controller.getNodesWhitelist()) assertThat(controller.getNodesWhitelist()).containsExactly(expectedEnodeURI);
.containsExactly(DefaultPeer.fromURI(expectedEnodeURI));
} }
private Path createPermissionsFileWithNode(final String node) throws IOException { private Path createPermissionsFileWithNode(final String node) throws IOException {

@ -49,10 +49,10 @@ import tech.pegasys.pantheon.ethereum.p2p.config.RlpxConfiguration;
import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration; import tech.pegasys.pantheon.ethereum.p2p.config.SubProtocolConfiguration;
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.ethereum.p2p.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.p2p.wire.Capability; import tech.pegasys.pantheon.ethereum.p2p.wire.Capability;
import tech.pegasys.pantheon.ethereum.p2p.wire.SubProtocol; import tech.pegasys.pantheon.ethereum.p2p.wire.SubProtocol;
import tech.pegasys.pantheon.ethereum.permissioning.AccountWhitelistController; import tech.pegasys.pantheon.ethereum.permissioning.AccountWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.NodeWhitelistController;
import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration; import tech.pegasys.pantheon.ethereum.permissioning.PermissioningConfiguration;
import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionHandler; import tech.pegasys.pantheon.ethereum.privacy.PrivateTransactionHandler;
import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive; import tech.pegasys.pantheon.ethereum.worldstate.WorldStateArchive;

@ -143,6 +143,22 @@ public class EnodeURL {
return value.contains("discport"); return value.contains("discport");
} }
public String getNodeId() {
return nodeId;
}
public String getIp() {
return ip;
}
public Integer getListeningPort() {
return listeningPort;
}
public OptionalInt getDiscoveryPort() {
return discoveryPort;
}
@Override @Override
public boolean equals(final Object o) { public boolean equals(final Object o) {
if (this == o) { if (this == o) {
@ -162,4 +178,9 @@ public class EnodeURL {
public int hashCode() { public int hashCode() {
return Objects.hashCode(nodeId, ip, listeningPort, discoveryPort); return Objects.hashCode(nodeId, ip, listeningPort, discoveryPort);
} }
@Override
public String toString() {
return this.toURI().toString();
}
} }

Loading…
Cancel
Save