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) 2014-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 starting bitcoind with -bind and/or -bind=...=onion, confirm that7it binds to the expected ports, and verify that duplicate or conflicting8-bind/-whitebind configurations are rejected with a descriptive error.9"""11from itertools import combinations_with_replacement12from test_framework.netutil import (13addr_to_hex,14get_bind_addrs,15)16from test_framework.test_framework import (17BitcoinTestFramework,18)19from test_framework.test_node import ErrorMatch20from test_framework.util import (21assert_equal,22p2p_port,23rpc_port,24)26class BindExtraTest(BitcoinTestFramework):27def set_test_params(self):28self.setup_clean_chain = True29# Avoid any -bind= on the command line. Force the framework to avoid30# adding -bind=127.0.0.1.31self.bind_to_localhost_only = False32self.num_nodes = 334def skip_test_if_missing_module(self):35self.skip_if_platform_not_posix()36self.skip_if_no_lsof_on_nonlinux()38def setup_network(self):39loopback_ipv4 = addr_to_hex("127.0.0.1")41# Start custom ports by reusing unused p2p ports42def extra_port():43port = p2p_port(extra_port.index)44extra_port.index += 145return port46extra_port.index = self.num_nodes48# Array of tuples [command line arguments, expected bind addresses].49self.expected = []51# Node0, no normal -bind=... with -bind=...=onion, thus only the tor target.52port = extra_port()53self.expected.append(54[55[f"-bind=127.0.0.1:{port}=onion"],56[(loopback_ipv4, port)],57],58)60# Node1, both -bind=... and -bind=...=onion.61port = [extra_port(), extra_port()]62self.expected.append(63[64[f"-bind=127.0.0.1:{port[0]}", f"-bind=127.0.0.1:{port[1]}=onion"],65[(loopback_ipv4, port[0]), (loopback_ipv4, port[1])],66],67)69# Node2, no -bind=...=onion, thus no extra port for Tor target.70port = extra_port()71self.expected.append(72[73[f"-bind=127.0.0.1:{port}"],74[(loopback_ipv4, port)],75],76)78self.extra_args = list(map(lambda e: e[0], self.expected))79self.setup_nodes()81def run_test(self):82for i, (args, expected_services) in enumerate(self.expected):83self.log.info(f"Checking listening ports of node {i} with {args}")84pid = self.nodes[i].process.pid85binds = set(get_bind_addrs(pid))86# Remove IPv6 addresses because on some CI environments "::1" is not configured87# on the system (so our test_ipv6_local() would return False), but it is88# possible to bind on "::". This makes it unpredictable whether to expect89# that bitcoind has bound on "::1" (for RPC) and "::" (for P2P).90ipv6_addr_len_bytes = 3291binds = set(filter(lambda e: len(e[0]) != ipv6_addr_len_bytes, binds))92# Remove RPC ports. They are not relevant for this test.93binds = set(filter(lambda e: e[1] != rpc_port(i), binds))94assert_equal(binds, set(expected_services))96self.stop_node(0)98addr = "127.0.0.1:11012"99for opt1, opt2 in combinations_with_replacement([f"-bind={addr}", f"-bind={addr}=onion", f"-whitebind=noban@{addr}"], 2):100self.nodes[0].assert_start_raises_init_error(101[opt1, opt2],102"Error: Duplicate binding configuration",103match=ErrorMatch.PARTIAL_REGEX)105if __name__ == '__main__':106BindExtraTest(__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.