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()