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