-
Notifications
You must be signed in to change notification settings - Fork 130
[PAN-2595] Consolidate local enode representation #1376
[PAN-2595] Consolidate local enode representation #1376
Conversation
Peers can be added to the maintained peer list before the network is fully started and permissions can be properly checked. So, for consistency, don't gate addition to the maintained peer list using permissions. Just don't connect to peers who are currently not allowed.
@@ -59,12 +59,6 @@ public TestNode create( | |||
return node; | |||
} | |||
|
|||
public void startNetworks() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Each individual network is already started here
|
||
/** | ||
* 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<Optional<EnodeURL>> selfEnode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, we passed in a static EnodeURL
constructed in RunnerBuilder
. This enode wasn't 100% accurate as the network can be configured to choose a port on startup, and the representation constructed in the builder would not accurately reflect the real ports being used. We're now passing a supplier that returns the canonical local enode representation when available.
} 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(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll now only return an answer when the network is ready.
* @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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously, peer permission would be checked as peers were added to this list. The changes in this PR delay the point at which we're able to check permission to the point where our local node is up and running. As a result, if we were to gate entrance into the list based on permissions, there would be a period where no nodes could be added to this list while the node is starting up. So, this API has been updated such that a peer can be added to the "maintain connection" list whether or not it is permitted on the network. However, no peers will actually be connected to without first checking permissions.
@@ -346,7 +347,7 @@ protected void initChannel(final SocketChannel ch) { | |||
return; | |||
} | |||
|
|||
if (!isPeerConnectionAllowed(connection)) { | |||
if (!isPeerAllowed(connection)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Permission checks have been centralized to one method.
void checkMaintainedConnectionPeers() { | ||
peerMaintainConnectionList.stream() | ||
.filter(p -> !isConnectingOrConnected(p)) | ||
.filter(this::isPeerAllowed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check permissions before connecting :\
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we drop them from the maintained list if they aren't permitted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so. The peer might later be permitted.
if (!blockAddedObserverId.isPresent()) { | ||
blockAddedObserverId = | ||
OptionalLong.of(blockchain.get().observeBlockAdded(this::handleBlockAddedEvent)); | ||
if (started.compareAndSet(false, true)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Start can be called at most once
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Should we switch this to use an early exit pattern rather than wrapping the whole method in an if?
return false; | ||
} | ||
|
||
Optional<EnodeURL> maybeEnode = getLocalEnode(); | ||
if (!maybeEnode.isPresent()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Be restrictive around permissions until we have a valid representation of our local enode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Would just be good to confirm the permissioning related changes with someone from Bunyip.
if (!blockAddedObserverId.isPresent()) { | ||
blockAddedObserverId = | ||
OptionalLong.of(blockchain.get().observeBlockAdded(this::handleBlockAddedEvent)); | ||
if (started.compareAndSet(false, true)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Should we switch this to use an early exit pattern rather than wrapping the whole method in an if?
} | ||
|
||
private EnodeURL buildSelfEnodeURL() { | ||
private void setLocalEnode() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: this probably should be createLocalEnode
since it doesn't follow the typical setter pattern.
final Peer peer = mockPeer(); | ||
network.peerMaintainConnectionList.add(peer); | ||
|
||
network.checkMaintainedConnectionPeers(); | ||
verify(network, times(1)).connect(peer); | ||
} | ||
|
||
@Test | ||
public void checkMaintainedConnectionPeersDoesNotConnectToDisallowedPeer() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lucassaldanha can you confirm that the permissioning controls should prevent peers added via staticnodes.json or admin_addPeer from connecting? It makes sense to me but I seem to recall some discussions and details...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the staticnodes.json list we apply the same rules as for bootnodes: they must be permitted.
For admin_addPeer is the same logic as connecting to another peer. If the peer is not allowed it won't connect to the peer (and I believe the addPeer method will give you a nice error response saying why).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "admin_addPeer" method will no longer return error messages if a non-permitted peer is added. Discussed this with @lucassaldanha offline and we determined that there is no need to keep these error messages.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. My only question is if we should remove peers not allowed from the maintained peer list at the moment we find out they aren't allowed.
void checkMaintainedConnectionPeers() { | ||
peerMaintainConnectionList.stream() | ||
.filter(p -> !isConnectingOrConnected(p)) | ||
.filter(this::isPeerAllowed) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we drop them from the maintained list if they aren't permitted?
I'd be inclined to keep forbidden peers in the maintained list because they may become permitted later - especially with on-chain permissioning. You may have setup a new node, added it as a peer for your existing nodes and are now getting approvals from the consortium to allow it to actually connect. |
PR description
This PR consolidates local enode representations around a single canonical representation. Previously, there were a few places where we would construct
EnodeURL
instances to represent the local node. However, this representation is only truly accurate once the network starts up as ports can be chosen on startup.