/ test / functional / p2p_addrv2_relay.py
p2p_addrv2_relay.py
  1  #!/usr/bin/env python3
  2  # Copyright (c) 2020-present 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  """
  6  Test addrv2 relay
  7  """
  8  
  9  import time
 10  
 11  from test_framework.messages import (
 12      CAddress,
 13      msg_addrv2,
 14      msg_sendaddrv2,
 15  )
 16  from test_framework.p2p import (
 17      P2PInterface,
 18      P2P_SERVICES,
 19  )
 20  from test_framework.test_framework import BitcoinTestFramework
 21  from test_framework.util import assert_equal
 22  
 23  I2P_ADDR = "c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p"
 24  ONION_ADDR = "pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"
 25  
 26  ADDRS = []
 27  for i in range(10):
 28      addr = CAddress()
 29      addr.time = int(time.time()) + i
 30      addr.port = 8333 + i
 31      addr.nServices = P2P_SERVICES
 32      # Add one I2P and one onion V3 address at an arbitrary position.
 33      if i == 5:
 34          addr.net = addr.NET_I2P
 35          addr.ip = I2P_ADDR
 36          addr.port = 0
 37      elif i == 8:
 38          addr.net = addr.NET_TORV3
 39          addr.ip = ONION_ADDR
 40      else:
 41          addr.ip = f"123.123.123.{i % 256}"
 42      ADDRS.append(addr)
 43  
 44  
 45  class AddrReceiver(P2PInterface):
 46      addrv2_received_and_checked = False
 47  
 48      def __init__(self):
 49          super().__init__(support_addrv2 = True)
 50  
 51      def on_addrv2(self, message):
 52          expected_set = set((addr.ip, addr.port) for addr in ADDRS)
 53          received_set = set((addr.ip, addr.port) for addr in message.addrs)
 54          if expected_set == received_set:
 55              self.addrv2_received_and_checked = True
 56  
 57      def wait_for_addrv2(self):
 58          self.wait_until(lambda: "addrv2" in self.last_message)
 59  
 60  
 61  def calc_addrv2_msg_size(addrs):
 62      size = 1  # vector length byte
 63      for addr in addrs:
 64          size += 4  # time
 65          size += 1  # services, COMPACTSIZE(P2P_SERVICES)
 66          size += 1  # network id
 67          size += 1  # address length byte
 68          size += addr.ADDRV2_ADDRESS_LENGTH[addr.net]  # address
 69          size += 2  # port
 70      return size
 71  
 72  class AddrTest(BitcoinTestFramework):
 73      def set_test_params(self):
 74          self.setup_clean_chain = True
 75          self.num_nodes = 1
 76          self.extra_args = [["-whitelist=addr@127.0.0.1"]]
 77  
 78      def run_test(self):
 79          self.log.info('Check disconnection when sending sendaddrv2 after verack')
 80          conn = self.nodes[0].add_p2p_connection(P2PInterface())
 81          with self.nodes[0].assert_debug_log(['sendaddrv2 received after verack, disconnecting peer=0']):
 82              conn.send_without_ping(msg_sendaddrv2())
 83              conn.wait_for_disconnect()
 84  
 85          self.log.info('Create connection that sends addrv2 messages')
 86          addr_source = self.nodes[0].add_p2p_connection(P2PInterface())
 87          msg = msg_addrv2()
 88  
 89          self.log.info('Check that addrv2 message content is relayed and added to addrman')
 90          addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
 91          msg.addrs = ADDRS
 92          msg_size = calc_addrv2_msg_size(ADDRS)
 93          with self.nodes[0].assert_debug_log([
 94                  f'received: addrv2 ({msg_size} bytes) peer=1',
 95                  f'sending addrv2 ({msg_size} bytes) peer=2',
 96          ]):
 97              addr_source.send_and_ping(msg)
 98              self.nodes[0].setmocktime(int(time.time()) + 30 * 60)
 99              addr_receiver.wait_for_addrv2()
100  
101          assert addr_receiver.addrv2_received_and_checked
102          assert_equal(len(self.nodes[0].getnodeaddresses(count=0, network="i2p")), 0)
103  
104          self.log.info('Send too-large addrv2 message')
105          msg.addrs = ADDRS * 101
106          with self.nodes[0].assert_debug_log(['addrv2 message size = 1010']):
107              addr_source.send_without_ping(msg)
108              addr_source.wait_for_disconnect()
109  
110  
111  
112  if __name__ == '__main__':
113      AddrTest(__file__).main()