diff --git a/test/functional/p2p_leak.py b/test/functional/p2p_leak.py --- a/test/functional/p2p_leak.py +++ b/test/functional/p2p_leak.py @@ -16,7 +16,6 @@ from test_framework.messages import ( msg_getaddr, msg_ping, - msg_verack, msg_version, ) from test_framework.p2p import ( @@ -33,7 +32,7 @@ DISCOURAGEMENT_THRESHOLD = 10 -class CLazyNode(P2PInterface): +class LazyPeer(P2PInterface): def __init__(self): super().__init__() self.unexpected_msg = False @@ -47,6 +46,7 @@ def on_open(self): self.ever_connected = True + # Does not respond to "version" with "verack" def on_version(self, message): self.bad_message(message) def on_verack(self, message): self.bad_message(message) @@ -88,27 +88,8 @@ def on_blocktxn(self, message): self.bad_message(message) -# Node that never sends a version. We'll use this to send a bunch of messages -# anyway, and eventually get disconnected. - - -class CNodeNoVersionMisbehavior(CLazyNode): - pass - - -# Node that never sends a version. This one just sits idle and hopes to receive -# any message (it shouldn't!) - - -class CNodeNoVersionIdle(CLazyNode): - def __init__(self): - super().__init__() - - -# Node that sends a version but not a verack. - - -class CNodeNoVerackIdle(CLazyNode): +# Peer that sends a version but not a verack. +class NoVerackIdlePeer(LazyPeer): def __init__(self): self.version_received = False super().__init__() @@ -128,6 +109,7 @@ version_received = None def on_version(self, msg): + # Responds with an appropriate verack super().on_version(msg) self.version_received = msg @@ -137,47 +119,54 @@ self.num_nodes = 1 def run_test(self): - no_version_disconnect_node = self.nodes[0].add_p2p_connection( - CNodeNoVersionMisbehavior(), send_version=False, wait_for_verack=False) - no_version_idlenode = self.nodes[0].add_p2p_connection( - CNodeNoVersionIdle(), send_version=False, wait_for_verack=False) - no_verack_idlenode = self.nodes[0].add_p2p_connection( - CNodeNoVerackIdle(), wait_for_verack=False) - - # Send enough veracks without a message to reach the peer discouragement - # threshold. This should get us disconnected. + # Peer that never sends a version. We will send a bunch of messages + # from this peer anyway and verify eventual disconnection. + no_version_disconnect_peer = self.nodes[0].add_p2p_connection( + LazyPeer(), send_version=False, wait_for_verack=False) + + # Another peer that never sends a version, nor any other messages. + # It shouldn't receive anything from the node. + no_version_idle_peer = self.nodes[0].add_p2p_connection( + LazyPeer(), send_version=False, wait_for_verack=False) + + # Peer that sends a version but not a verack. + no_verack_idle_peer = self.nodes[0].add_p2p_connection( + NoVerackIdlePeer(), wait_for_verack=False) + + # Send enough ping messages (any non-version message will do) prior + # to sending version to reach the peer discouragement threshold. This + # should get us disconnected. for _ in range(DISCOURAGEMENT_THRESHOLD): - no_version_disconnect_node.send_message(msg_verack()) + no_version_disconnect_peer.send_message(msg_ping()) - # Wait until we got the verack in response to the version. Though, don't wait for the other node to receive the + # Wait until we got the verack in response to the version. Though, don't wait for the node to receive the # verack, since we never sent one - no_verack_idlenode.wait_for_verack() + no_verack_idle_peer.wait_for_verack() wait_until( - lambda: no_version_disconnect_node.ever_connected, + lambda: no_version_disconnect_peer.ever_connected, timeout=10, lock=p2p_lock) - wait_until(lambda: no_version_idlenode.ever_connected, + wait_until(lambda: no_version_idle_peer.ever_connected, timeout=10, lock=p2p_lock) - wait_until(lambda: no_verack_idlenode.version_received, + wait_until(lambda: no_verack_idle_peer.version_received, timeout=10, lock=p2p_lock) - # Mine a block and make sure that it's not sent to the connected nodes - self.nodes[0].generatetoaddress( - 1, self.nodes[0].get_deterministic_priv_key().address) + # Mine a block and make sure that it's not sent to the connected peers + self.nodes[0].generate(nblocks=1) # Give the node enough time to possibly leak out a message time.sleep(5) - # Expect this node to be disconnected for misbehavior - assert not no_version_disconnect_node.is_connected + # Expect this peer to be disconnected for misbehavior + assert not no_version_disconnect_peer.is_connected self.nodes[0].disconnect_p2ps() # Make sure no unexpected messages came in - assert not no_version_disconnect_node.unexpected_msg - assert not no_version_idlenode.unexpected_msg - assert not no_verack_idlenode.unexpected_msg + assert not no_version_disconnect_peer.unexpected_msg + assert not no_version_idle_peer.unexpected_msg + assert not no_verack_idle_peer.unexpected_msg self.log.info( 'Check that the version message does not leak the local address of the node') @@ -191,14 +180,14 @@ assert_equal(ver.nStartingHeight, 201) assert_equal(ver.nRelay, 1) - self.log.info('Check that old nodes are disconnected') - p2p_old_node = self.nodes[0].add_p2p_connection( + self.log.info('Check that old peers are disconnected') + p2p_old_peer = self.nodes[0].add_p2p_connection( P2PInterface(), send_version=False, wait_for_verack=False) old_version_msg = msg_version() old_version_msg.nVersion = 31799 with self.nodes[0].assert_debug_log(['peer=4 using obsolete version 31799; disconnecting']): - p2p_old_node.send_message(old_version_msg) - p2p_old_node.wait_for_disconnect() + p2p_old_peer.send_message(old_version_msg) + p2p_old_peer.wait_for_disconnect() if __name__ == '__main__':