p2p_addrv2_relay.py raw

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