/ test / functional / p2p_add_connections.py
p2p_add_connections.py
  1  #!/usr/bin/env python3
  2  # Copyright (c) 2020-2021 The Bitcoin Core developers
  3  # Distributed under the MIT software license, see the accompanying
  4  # file COPYING or http://www.opensource.org/licenses/mit-license.php.
  5  """Test add_outbound_p2p_connection test framework functionality"""
  6  
  7  from test_framework.p2p import P2PInterface
  8  from test_framework.test_framework import BitcoinTestFramework
  9  from test_framework.util import (
 10      assert_equal,
 11      check_node_connections,
 12  )
 13  
 14  class P2PFeelerReceiver(P2PInterface):
 15      def on_version(self, message):
 16          # The bitcoind node closes feeler connections as soon as a version
 17          # message is received from the test framework. Don't send any responses
 18          # to the node's version message since the connection will already be
 19          # closed.
 20          self.send_version()
 21  
 22  class P2PAddConnections(BitcoinTestFramework):
 23      def set_test_params(self):
 24          self.num_nodes = 2
 25  
 26      def setup_network(self):
 27          self.setup_nodes()
 28          # Don't connect the nodes
 29  
 30      def run_test(self):
 31          self.log.info("Add 8 outbounds to node 0")
 32          for i in range(8):
 33              self.log.info(f"outbound: {i}")
 34              self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="outbound-full-relay")
 35  
 36          self.log.info("Add 2 block-relay-only connections to node 0")
 37          for i in range(2):
 38              self.log.info(f"block-relay-only: {i}")
 39              # set p2p_idx based on the outbound connections already open to the
 40              # node, so add 8 to account for the previous full-relay connections
 41              self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i + 8, connection_type="block-relay-only")
 42  
 43          self.log.info("Add 2 block-relay-only connections to node 1")
 44          for i in range(2):
 45              self.log.info(f"block-relay-only: {i}")
 46              self.nodes[1].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i, connection_type="block-relay-only")
 47  
 48          self.log.info("Add 5 inbound connections to node 1")
 49          for i in range(5):
 50              self.log.info(f"inbound: {i}")
 51              self.nodes[1].add_p2p_connection(P2PInterface())
 52  
 53          self.log.info("Add 8 outbounds to node 1")
 54          for i in range(8):
 55              self.log.info(f"outbound: {i}")
 56              # bump p2p_idx to account for the 2 existing outbounds on node 1
 57              self.nodes[1].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i + 2)
 58  
 59          self.log.info("Check the connections opened as expected")
 60          check_node_connections(node=self.nodes[0], num_in=0, num_out=10)
 61          check_node_connections(node=self.nodes[1], num_in=5, num_out=10)
 62  
 63          self.log.info("Disconnect p2p connections & try to re-open")
 64          self.nodes[0].disconnect_p2ps()
 65          check_node_connections(node=self.nodes[0], num_in=0, num_out=0)
 66  
 67          self.log.info("Add 8 outbounds to node 0")
 68          for i in range(8):
 69              self.log.info(f"outbound: {i}")
 70              self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i)
 71          check_node_connections(node=self.nodes[0], num_in=0, num_out=8)
 72  
 73          self.log.info("Add 2 block-relay-only connections to node 0")
 74          for i in range(2):
 75              self.log.info(f"block-relay-only: {i}")
 76              # bump p2p_idx to account for the 8 existing outbounds on node 0
 77              self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i + 8, connection_type="block-relay-only")
 78          check_node_connections(node=self.nodes[0], num_in=0, num_out=10)
 79  
 80          self.log.info("Restart node 0 and try to reconnect to p2ps")
 81          self.restart_node(0)
 82  
 83          self.log.info("Add 4 outbounds to node 0")
 84          for i in range(4):
 85              self.log.info(f"outbound: {i}")
 86              self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i)
 87          check_node_connections(node=self.nodes[0], num_in=0, num_out=4)
 88  
 89          self.log.info("Add 2 block-relay-only connections to node 0")
 90          for i in range(2):
 91              self.log.info(f"block-relay-only: {i}")
 92              # bump p2p_idx to account for the 4 existing outbounds on node 0
 93              self.nodes[0].add_outbound_p2p_connection(P2PInterface(), p2p_idx=i + 4, connection_type="block-relay-only")
 94          check_node_connections(node=self.nodes[0], num_in=0, num_out=6)
 95  
 96          check_node_connections(node=self.nodes[1], num_in=5, num_out=10)
 97  
 98          self.log.info("Add 1 feeler connection to node 0")
 99          feeler_conn = self.nodes[0].add_outbound_p2p_connection(P2PFeelerReceiver(), p2p_idx=6, connection_type="feeler")
100  
101          # Feeler connection is closed
102          assert not feeler_conn.is_connected
103  
104          # Verify version message received
105          assert_equal(feeler_conn.message_count["version"], 1)
106          # Feeler connections do not request tx relay
107          assert_equal(feeler_conn.last_message["version"].relay, 0)
108  
109  if __name__ == '__main__':
110      P2PAddConnections().main()