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"""6Test that -discover does not add all interfaces' addresses if we listen on only some of them7"""9import os11from test_framework.test_framework import BitcoinTestFramework, SkipTest12from test_framework.test_node import (13FailedToStartError,14)15from test_framework.util import (16assert_equal,17assert_not_equal,18p2p_port,19tor_port,20)22# We need to bind to routable addresses for this test. Both addresses must be on an23# interface that is UP and not a loopback interface (IFF_LOOPBACK). To set these24# routable addresses on the machine, use:25# Linux:26# First find your interfaces: ip addr show27# Then use your actual interface names (replace INTERFACE_NAME with yours):28# ip addr add 1.1.1.5/32 dev INTERFACE_NAME && ip addr add 1111:1111::5/128 dev INTERFACE_NAME # to set up29# ip addr del 1.1.1.5/32 dev INTERFACE_NAME && ip addr del 1111:1111::5/128 dev INTERFACE_NAME # to remove it30#31# FreeBSD and MacOS:32# ifconfig INTERFACE_NAME 1.1.1.5/32 alias && ifconfig INTERFACE_NAME inet6 1111:1111::5/128 alias # to set up33# ifconfig INTERFACE_NAME 1.1.1.5 -alias && ifconfig INTERFACE_NAME inet6 1111:1111::5 -alias # to remove it, after the test34ADDR1 = os.getenv("BIND_TEST_ROUTABLE_IPV4", "1.1.1.5")35ADDR2 = os.getenv("BIND_TEST_ROUTABLE_IPV6", "1111:1111::5")37class BindPortDiscoverTest(BitcoinTestFramework):38def set_test_params(self):39# Avoid any -bind= on the command line. Force the framework to avoid adding -bind=127.0.0.1.40self.bind_to_localhost_only = False41# Get dynamic ports for each node from the test framework42self.bind_ports = [43p2p_port(0),44p2p_port(2), # node0 will use their port + 1 for onion listen, which is the same as p2p_port(1), so avoid collision45p2p_port(3),46p2p_port(4),47]48self.extra_args = [49['-discover', f'-port={self.bind_ports[0]}', '-listen=1'], # Without any -bind50['-discover', f'-bind=0.0.0.0:{self.bind_ports[1]}'], # Explicit -bind=0.0.0.051# Explicit -whitebind=0.0.0.0, add onion bind to avoid port conflict52['-discover', f'-whitebind=0.0.0.0:{self.bind_ports[2]}', f'-bind=127.0.0.1:{tor_port(3)}=onion'],53['-discover', f'-bind={ADDR1}:{self.bind_ports[3]}'], # Explicit -bind=routable_addr54]55self.num_nodes = len(self.extra_args)57def setup_network(self):58"""59Override to avoid connecting nodes together. This test intentionally does not connect nodes60because each node is bound to a different address or interface, and connections are not needed.61"""62self.setup_nodes()64def setup_nodes(self):65"""66Override to set has_explicit_bind=True for nodes with explicit bind arguments.67"""68self.add_nodes(self.num_nodes, self.extra_args)69# TestNode.start() will add -bind= to extra_args if has_explicit_bind is70# False. We do not want any -bind= thus set has_explicit_bind to True.71for node in self.nodes:72node.has_explicit_bind = True74try:75self.start_nodes()76except FailedToStartError as e:77self.cleanup_partially_started_nodes()78if 'Unable to bind to ' in str(e):79raise SkipTest(80"To run this test, set BIND_TEST_ROUTABLE_IPV4 and "81"BIND_TEST_ROUTABLE_IPV6 to addresses assigned to non-loopback "82f"interfaces on this machine (currently {ADDR1} and {ADDR2}).")83raise85def run_test(self):86self.log.info(87"Test that if -bind= is not passed or -bind=0.0.0.0 is used then all addresses are "88"added to localaddresses")89for i in [0, 1, 2]:90found_addr1 = False91found_addr2 = False92localaddresses = self.nodes[i].getnetworkinfo()['localaddresses']93for local in localaddresses:94if local['address'] == ADDR1:95found_addr1 = True96assert_equal(local['port'], self.bind_ports[i])97if local['address'] == ADDR2:98found_addr2 = True99assert_equal(local['port'], self.bind_ports[i])100if not found_addr1:101self.log.error(f"Address {ADDR1} not found in node{i}'s local addresses: {localaddresses}")102assert False103if not found_addr2:104self.log.error(f"Address {ADDR2} not found in node{i}'s local addresses: {localaddresses}")105assert False107self.log.info(108"Test that if -bind=routable_addr is passed then only that address is "109"added to localaddresses")110found_addr1 = False111i = 3112for local in self.nodes[i].getnetworkinfo()['localaddresses']:113if local['address'] == ADDR1:114found_addr1 = True115assert_equal(local['port'], self.bind_ports[i])116assert_not_equal(local['address'], ADDR2)117assert found_addr1119if __name__ == '__main__':120BindPortDiscoverTest(__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.