Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32# Copyright (c) 2020-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.5"""Test addr response caching"""7import time9from test_framework.p2p import (10P2PInterface,11p2p_lock12)13from test_framework.test_framework import BitcoinTestFramework14from test_framework.util import (15assert_not_equal,16assert_equal,17p2p_port,18)20# As defined in net_processing.21MAX_ADDR_TO_SEND = 100022MAX_PCT_ADDR_TO_SEND = 2325class AddrReceiver(P2PInterface):27def __init__(self):28super().__init__()29self.received_addrs = None31def get_received_addrs(self):32with p2p_lock:33return self.received_addrs35def on_addr(self, message):36self.received_addrs = []37for addr in message.addrs:38self.received_addrs.append(addr.ip)40def addr_received(self):41return self.received_addrs is not None44class AddrTest(BitcoinTestFramework):45def set_test_params(self):46self.num_nodes = 147# Use some of the remaining p2p ports for the onion binds.48self.onion_port1 = p2p_port(self.num_nodes)49self.onion_port2 = p2p_port(self.num_nodes + 1)50self.extra_args = [51[f"-bind=127.0.0.1:{self.onion_port1}=onion", f"-bind=127.0.0.1:{self.onion_port2}=onion"],52]54def run_test(self):55self.log.info('Fill peer AddrMan with a lot of records')56for i in range(10000):57first_octet = i >> 858second_octet = i % 25659a = "{}.{}.1.1".format(first_octet, second_octet)60self.nodes[0].addpeeraddress(a, 8333)62# Need to make sure we hit MAX_ADDR_TO_SEND records in the addr response later because63# only a fraction of all known addresses can be cached and returned.64assert len(self.nodes[0].getnodeaddresses(0)) > int(MAX_ADDR_TO_SEND / (MAX_PCT_ADDR_TO_SEND / 100))66last_response_on_local_bind = None67last_response_on_onion_bind1 = None68last_response_on_onion_bind2 = None69self.log.info('Send many addr requests within short time to receive same response')70N = 571cur_mock_time = int(time.time())72for i in range(N):73addr_receiver_local = self.nodes[0].add_p2p_connection(AddrReceiver())74addr_receiver_onion1 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port1)75addr_receiver_onion2 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port2)77# Trigger response78cur_mock_time += 5 * 6079self.nodes[0].setmocktime(cur_mock_time)80addr_receiver_local.wait_until(addr_receiver_local.addr_received)81addr_receiver_onion1.wait_until(addr_receiver_onion1.addr_received)82addr_receiver_onion2.wait_until(addr_receiver_onion2.addr_received)84if i > 0:85# Responses from different binds should be unique86assert_not_equal(last_response_on_local_bind, addr_receiver_onion1.get_received_addrs())87assert_not_equal(last_response_on_local_bind, addr_receiver_onion2.get_received_addrs())88assert_not_equal(last_response_on_onion_bind1, addr_receiver_onion2.get_received_addrs())89# Responses on from the same bind should be the same90assert_equal(last_response_on_local_bind, addr_receiver_local.get_received_addrs())91assert_equal(last_response_on_onion_bind1, addr_receiver_onion1.get_received_addrs())92assert_equal(last_response_on_onion_bind2, addr_receiver_onion2.get_received_addrs())94last_response_on_local_bind = addr_receiver_local.get_received_addrs()95last_response_on_onion_bind1 = addr_receiver_onion1.get_received_addrs()96last_response_on_onion_bind2 = addr_receiver_onion2.get_received_addrs()98for response in [last_response_on_local_bind, last_response_on_onion_bind1, last_response_on_onion_bind2]:99assert_equal(len(response), MAX_ADDR_TO_SEND)101cur_mock_time += 3 * 24 * 60 * 60102self.nodes[0].setmocktime(cur_mock_time)104self.log.info('After time passed, see a new response to addr request')105addr_receiver_local = self.nodes[0].add_p2p_connection(AddrReceiver())106addr_receiver_onion1 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port1)107addr_receiver_onion2 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port2)109# Trigger response110cur_mock_time += 5 * 60111self.nodes[0].setmocktime(cur_mock_time)112addr_receiver_local.wait_until(addr_receiver_local.addr_received)113addr_receiver_onion1.wait_until(addr_receiver_onion1.addr_received)114addr_receiver_onion2.wait_until(addr_receiver_onion2.addr_received)116# new response is different117assert_not_equal(set(last_response_on_local_bind), set(addr_receiver_local.get_received_addrs()))118assert_not_equal(set(last_response_on_onion_bind1), set(addr_receiver_onion1.get_received_addrs()))119assert_not_equal(set(last_response_on_onion_bind2), set(addr_receiver_onion2.get_received_addrs()))122if __name__ == '__main__':123AddrTest(__file__).main()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.