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.
251proxies=[self.serv3, self.serv3, self.serv3, self.serv3],252auth=False, test_onion=False, test_cjdns=False)254# -proxy=unauth -proxyrandomize=1 -cjdnsreachable255self.node_test(self.nodes[4],256proxies=[self.serv1, self.serv1, self.serv1, self.serv1],257auth=False, test_onion=True, test_cjdns=True)259if self.have_unix_sockets:260self.node_test(self.nodes[5],261proxies=[self.serv4, self.serv4, self.serv4, self.serv4],262auth=True, test_onion=True, test_cjdns=False)265def networks_dict(d):266r = {}267for x in d['networks']:268r[x['name']] = x269return r271self.log.info("Test RPC getnetworkinfo")272nodes_network_info = []274self.log.debug("Test that setting -proxy disables local address discovery, i.e. -discover=0")275for node in self.nodes:276network_info = node.getnetworkinfo()277assert_equal(network_info["localaddresses"], [])278nodes_network_info.append(network_info)280n0 = networks_dict(nodes_network_info[0])281assert_equal(NETWORKS, n0.keys())282for net in NETWORKS:283if net == NET_I2P:284expected_proxy = ''285expected_randomize = False286else:287expected_proxy = '%s:%i' % (self.conf1.addr)288expected_randomize = True289assert_equal(n0[net]['proxy'], expected_proxy)290assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize)291assert_equal(n0['onion']['reachable'], True)292assert_equal(n0['i2p']['reachable'], False)293assert_equal(n0['cjdns']['reachable'], False)295n1 = networks_dict(nodes_network_info[1])296assert_equal(NETWORKS, n1.keys())297for net in ['ipv4', 'ipv6']:298assert_equal(n1[net]['proxy'], f'{self.conf1.addr[0]}:{self.conf1.addr[1]}')299assert_equal(n1[net]['proxy_randomize_credentials'], False)300assert_equal(n1['onion']['proxy'], f'{self.conf2.addr[0]}:{self.conf2.addr[1]}')301assert_equal(n1['onion']['proxy_randomize_credentials'], False)302assert_equal(n1['onion']['reachable'], True)303assert_equal(n1['i2p']['proxy'], f'{self.i2p_sam[0]}:{self.i2p_sam[1]}')304assert_equal(n1['i2p']['proxy_randomize_credentials'], False)305assert_equal(n1['i2p']['reachable'], True)307n2 = networks_dict(nodes_network_info[2])308assert_equal(NETWORKS, n2.keys())309proxy = f'{self.conf2.addr[0]}:{self.conf2.addr[1]}'310for net in NETWORKS:311if net == NET_I2P:312expected_proxy = ''313expected_randomize = False314else:315expected_proxy = proxy316expected_randomize = True317assert_equal(n2[net]['proxy'], expected_proxy)318assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize)319assert_equal(n2['onion']['reachable'], True)320assert_equal(n2['i2p']['reachable'], False)321assert_equal(n2['cjdns']['reachable'], False)323if self.have_ipv6:324n3 = networks_dict(nodes_network_info[3])325assert_equal(NETWORKS, n3.keys())326proxy = f'[{self.conf3.addr[0]}]:{self.conf3.addr[1]}'327for net in NETWORKS:328expected_proxy = '' if net == NET_I2P or net == NET_ONION else proxy329assert_equal(n3[net]['proxy'], expected_proxy)330assert_equal(n3[net]['proxy_randomize_credentials'], False)331assert_equal(n3['onion']['reachable'], False)332assert_equal(n3['i2p']['reachable'], False)333assert_equal(n3['cjdns']['reachable'], False)335n4 = networks_dict(nodes_network_info[4])336assert_equal(NETWORKS, n4.keys())337for net in NETWORKS:338if net == NET_I2P:339expected_proxy = ''340expected_randomize = False341else:342expected_proxy = '%s:%i' % (self.conf1.addr)343expected_randomize = True344assert_equal(n4[net]['proxy'], expected_proxy)345assert_equal(n4[net]['proxy_randomize_credentials'], expected_randomize)346assert_equal(n4['onion']['reachable'], True)347assert_equal(n4['i2p']['reachable'], False)348assert_equal(n4['cjdns']['reachable'], True)350if self.have_unix_sockets:351n5 = networks_dict(nodes_network_info[5])352assert_equal(NETWORKS, n5.keys())353for net in NETWORKS:354if net == NET_I2P:355expected_proxy = ''356expected_randomize = False357else:358expected_proxy = 'unix:' + self.conf4.addr # no port number359expected_randomize = True360assert_equal(n5[net]['proxy'], expected_proxy)361assert_equal(n5[net]['proxy_randomize_credentials'], expected_randomize)362assert_equal(n5['onion']['reachable'], True)363assert_equal(n5['i2p']['reachable'], False)364assert_equal(n5['cjdns']['reachable'], False)366n6 = networks_dict(nodes_network_info[6])367assert_equal(NETWORKS, n6.keys())368for net in NETWORKS:369if net != NET_ONION:370expected_proxy = ''371expected_randomize = False372else:373expected_proxy = 'unix:' + self.conf4.addr # no port number374expected_randomize = True375assert_equal(n6[net]['proxy'], expected_proxy)376assert_equal(n6[net]['proxy_randomize_credentials'], expected_randomize)377assert_equal(n6['onion']['reachable'], True)378assert_equal(n6['i2p']['reachable'], False)379assert_equal(n6['cjdns']['reachable'], False)381self.stop_node(1)383self.log.info("Test passing invalid -proxy hostname raises expected init error")384self.nodes[1].extra_args = ["-proxy=abc..abc:23456"]385msg = "Error: Invalid -proxy address or hostname: 'abc..abc:23456'"386self.nodes[1].assert_start_raises_init_error(expected_msg=msg)388self.log.info("Test passing invalid -proxy port raises expected init error")389self.nodes[1].extra_args = ["-proxy=192.0.0.1:def"]390msg = "Error: Invalid port specified in -proxy: '192.0.0.1:def'"391self.nodes[1].assert_start_raises_init_error(expected_msg=msg)393self.log.info("Test passing invalid -onion hostname raises expected init error")394self.nodes[1].extra_args = ["-onion=xyz..xyz:23456"]395msg = "Error: Invalid -onion address or hostname: 'xyz..xyz:23456'"396self.nodes[1].assert_start_raises_init_error(expected_msg=msg)398self.log.info("Test passing invalid -onion port raises expected init error")399self.nodes[1].extra_args = ["-onion=192.0.0.1:def"]400msg = "Error: Invalid port specified in -onion: '192.0.0.1:def'"401self.nodes[1].assert_start_raises_init_error(expected_msg=msg)403self.log.info("Test passing invalid -i2psam hostname raises expected init error")404self.nodes[1].extra_args = ["-i2psam=def..def:23456"]405msg = "Error: Invalid -i2psam address or hostname: 'def..def:23456'"406self.nodes[1].assert_start_raises_init_error(expected_msg=msg)408self.log.info("Test passing invalid -i2psam port raises expected init error")409self.nodes[1].extra_args = ["-i2psam=192.0.0.1:def"]410msg = "Error: Invalid port specified in -i2psam: '192.0.0.1:def'"411self.nodes[1].assert_start_raises_init_error(expected_msg=msg)413self.log.info("Test passing invalid -onlynet=i2p without -i2psam raises expected init error")414self.nodes[1].extra_args = ["-onlynet=i2p"]415msg = "Error: Outbound connections restricted to i2p (-onlynet=i2p) but -i2psam is not provided"416self.nodes[1].assert_start_raises_init_error(expected_msg=msg)418self.log.info("Test passing invalid -onlynet=cjdns without -cjdnsreachable raises expected init error")419self.nodes[1].extra_args = ["-onlynet=cjdns"]420msg = "Error: Outbound connections restricted to CJDNS (-onlynet=cjdns) but -cjdnsreachable is not provided"421self.nodes[1].assert_start_raises_init_error(expected_msg=msg)423self.log.info("Test passing -onlynet=onion with -onion=0/-noonion raises expected init error")424msg = (425"Error: Outbound connections restricted to Tor (-onlynet=onion) but "426"the proxy for reaching the Tor network is explicitly forbidden: -onion=0"427)428for arg in ["-onion=0", "-noonion"]:429self.nodes[1].extra_args = ["-onlynet=onion", arg]430self.nodes[1].assert_start_raises_init_error(expected_msg=msg)432self.log.info("Test passing -onlynet=onion without -proxy, -onion or -listenonion raises expected init error")433self.nodes[1].extra_args = ["-onlynet=onion", "-listenonion=0"]434msg = (435"Error: Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "436"reaching the Tor network is not provided: none of -proxy, -onion or -listenonion is given"437)438self.nodes[1].assert_start_raises_init_error(expected_msg=msg)440self.log.info("Test passing -onlynet=onion without -proxy or -onion but with -listenonion=1 is ok")441self.start_node(1, extra_args=["-onlynet=onion", "-listenonion=1"])442self.stop_node(1)444self.log.info("Test unknown and removed network names are rejected by -onlynet")445for network in ["abc", "tor"]:446self.nodes[1].extra_args = [f"-onlynet={network}"]447msg = f"Error: Unknown network specified in -onlynet: '{network}'"448self.nodes[1].assert_start_raises_init_error(expected_msg=msg)450self.log.info("Test passing trailing '=' raises expected init error")451self.nodes[1].extra_args = ["-proxy=127.0.0.1:9050="]452msg = "Error: Invalid -proxy address or hostname, ends with '=': '127.0.0.1:9050='"453self.nodes[1].assert_start_raises_init_error(expected_msg=msg)455self.log.info("Test unknown, removed and non-SOCKS5 network names are rejected by -proxy")456for network in ["Foo", "tor", "i2p"]:457self.nodes[1].extra_args = [f"-proxy=127.0.0.1:9050={network}"]458msg = f"Error: Unrecognized network in -proxy='127.0.0.1:9050={network}': '{network}'"459self.nodes[1].assert_start_raises_init_error(expected_msg=msg)461self.log.info("Test passing proxy only for IPv6")462self.start_node(1, extra_args=["-proxy=127.6.6.6:6666=ipv6"])463nets = networks_dict(self.nodes[1].getnetworkinfo())464assert_equal(nets["ipv4"]["proxy"], "")465assert_equal(nets["ipv6"]["proxy"], "127.6.6.6:6666")466self.stop_node(1)468self.log.info("Test passing separate proxy for IPv4 and IPv6")469self.start_node(1, extra_args=["-proxy=127.4.4.4:4444=ipv4", "-proxy=127.6.6.6:6666=ipv6"])470nets = networks_dict(self.nodes[1].getnetworkinfo())471assert_equal(nets["ipv4"]["proxy"], "127.4.4.4:4444")472assert_equal(nets["ipv6"]["proxy"], "127.6.6.6:6666")473self.stop_node(1)475self.log.info("Test overriding the Onion proxy with a mixed-case network suffix")476self.start_node(1, extra_args=["-proxy=127.1.1.1:1111", "-proxy=127.2.2.2:2222=OnIoN"])477nets = networks_dict(self.nodes[1].getnetworkinfo())478assert_equal(nets["ipv4"]["proxy"], "127.1.1.1:1111")479assert_equal(nets["ipv6"]["proxy"], "127.1.1.1:1111")480assert_equal(nets["onion"]["proxy"], "127.2.2.2:2222")481self.stop_node(1)483self.log.info("Test removing CJDNS proxy")484self.start_node(1, extra_args=["-proxy=127.1.1.1:1111", "-proxy=0=cjdns"])485nets = networks_dict(self.nodes[1].getnetworkinfo())486assert_equal(nets["ipv4"]["proxy"], "127.1.1.1:1111")487assert_equal(nets["ipv6"]["proxy"], "127.1.1.1:1111")488assert_equal(nets["onion"]["proxy"], "127.1.1.1:1111")489assert_equal(nets["cjdns"]["proxy"], "")490self.stop_node(1)492self.log.info("Test that clearing the IPv4 proxy also clears the name proxy")493self.start_node(1, extra_args=[f"-proxy={self.conf1.addr[0]}:{self.conf1.addr[1]}", "-proxy=0=ipv4", "-dns=0"])494with self.nodes[1].assert_debug_log(495expected_msgs=["trying v1 connection (manual) to example.invalid:8333"],496unexpected_msgs=["SOCKS5 connecting example.invalid"],497):498self.nodes[1].addnode("example.invalid:8333", "onetry", v2transport=False)499self.stop_node(1)
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.