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// Copyright (c) 2023-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <chainparams.h>6#include <compat/compat.h>7#include <net.h>8#include <net_processing.h>9#include <netaddress.h>10#include <netbase.h>11#include <netgroup.h>12#include <node/connection_types.h>13#include <node/protocol_version.h>14#include <protocol.h>15#include <random.h>16#include <test/util/logging.h>17#include <test/util/net.h>18#include <test/util/random.h>19#include <test/util/setup_common.h>20#include <tinyformat.h>21#include <util/chaintype.h>23#include <algorithm>24#include <cstdint>25#include <memory>26#include <optional>27#include <string>28#include <vector>30#include <boost/test/unit_test.hpp>32struct LogIPsTestingSetup : public TestingSetup {33LogIPsTestingSetup()34: TestingSetup{ChainType::MAIN, {.extra_args = {"-logips"}}} {}35};37BOOST_FIXTURE_TEST_SUITE(net_peer_connection_tests, LogIPsTestingSetup)39static CService ip(uint32_t i)40{41struct in_addr s;42s.s_addr = i;43return CService{CNetAddr{s}, Params().GetDefaultPort()};44}46struct PeerTest : LogIPsTestingSetup {47/** Create a peer and connect to it. If the optional `address` (IP/CJDNS only) isn't passed, a random address is created. */48void AddPeer(NodeId& id, std::vector<CNode*>& nodes, PeerManager& peerman, ConnmanTestMsg& connman, ConnectionType conn_type, bool onion_peer = false, std::optional<std::string> address = std::nullopt)49{50CAddress addr{};52if (address.has_value()) {53addr = CAddress{MaybeFlipIPv6toCJDNS(LookupNumeric(address.value(), Params().GetDefaultPort())), NODE_NONE};54} else if (onion_peer) {55auto tor_addr{m_rng.randbytes(ADDR_TORV3_SIZE)};56BOOST_REQUIRE(addr.SetSpecial(OnionToString(tor_addr)));57}59while (!addr.IsLocal() && !addr.IsRoutable()) {60addr = CAddress{ip(m_rng.randbits(32)), NODE_NONE};61}63BOOST_REQUIRE(addr.IsValid());65const bool inbound_onion{onion_peer && conn_type == ConnectionType::INBOUND};67nodes.emplace_back(new CNode{++id,68/*sock=*/nullptr,69addr,70/*nKeyedNetGroupIn=*/0,71/*nLocalHostNonceIn=*/0,72CAddress{},73/*addrNameIn=*/"",74conn_type,75/*inbound_onion=*/inbound_onion,76/*network_key=*/0});77CNode& node = *nodes.back();78node.SetCommonVersion(PROTOCOL_VERSION);80peerman.InitializeNode(node, ServiceFlags(NODE_NETWORK | NODE_WITNESS));81node.fSuccessfullyConnected = true;83connman.AddTestNode(node);84}85}; // struct PeerTest87BOOST_FIXTURE_TEST_CASE(test_addnode_getaddednodeinfo_and_connection_detection, PeerTest)88{89auto connman = std::make_unique<ConnmanTestMsg>(0x1337, 0x1337, *m_node.addrman, *m_node.netgroupman, Params());90auto peerman = PeerManager::make(*connman, *m_node.addrman, nullptr, *m_node.chainman, *m_node.mempool, *m_node.warnings, {});91NodeId id{0};92std::vector<CNode*> nodes;94// Connect a localhost peer.95{96ASSERT_DEBUG_LOG("Added connection to 127.0.0.1:8333 peer=1");97AddPeer(id, nodes, *peerman, *connman, ConnectionType::MANUAL, /*onion_peer=*/false, /*address=*/"127.0.0.1");98BOOST_REQUIRE(nodes.back() != nullptr);99}101// Call ConnectNode(), which is also called by RPC addnode onetry, for a localhost102// address that resolves to multiple IPs, including that of the connected peer.103// The connection attempt should consistently fail due to the check in ConnectNode().104for (int i = 0; i < 10; ++i) {105ASSERT_DEBUG_LOG("Not opening a connection to localhost, already connected to 127.0.0.1:8333");106BOOST_CHECK(!connman->ConnectNodePublic(*peerman, "localhost", ConnectionType::MANUAL));107}109// Add 3 more peer connections.110AddPeer(id, nodes, *peerman, *connman, ConnectionType::OUTBOUND_FULL_RELAY);111AddPeer(id, nodes, *peerman, *connman, ConnectionType::BLOCK_RELAY, /*onion_peer=*/true);112AddPeer(id, nodes, *peerman, *connman, ConnectionType::INBOUND);114// Add a CJDNS peer connection.115AddPeer(id, nodes, *peerman, *connman, ConnectionType::INBOUND, /*onion_peer=*/false,116/*address=*/"[fc00:3344:5566:7788:9900:aabb:ccdd:eeff]:1234");117BOOST_CHECK(nodes.back()->IsInboundConn());118BOOST_CHECK_EQUAL(nodes.back()->ConnectedThroughNetwork(), Network::NET_CJDNS);120BOOST_TEST_MESSAGE("Call AddNode() for all the peers");121for (auto node : connman->TestNodes()) {122BOOST_CHECK(connman->AddNode({/*m_added_node=*/node->addr.ToStringAddrPort(), /*m_use_v2transport=*/true}));123BOOST_TEST_MESSAGE(strprintf("peer id=%s addr=%s", node->GetId(), node->addr.ToStringAddrPort()));124}126BOOST_TEST_MESSAGE("\nCall AddNode() with 2 addrs resolving to existing localhost addnode entry; neither should be added");127BOOST_CHECK(!connman->AddNode({/*m_added_node=*/"127.0.0.1", /*m_use_v2transport=*/true}));128// OpenBSD doesn't support the IPv4 shorthand notation with omitted zero-bytes.129#if !defined(__OpenBSD__)130BOOST_CHECK(!connman->AddNode({/*m_added_node=*/"127.1", /*m_use_v2transport=*/true}));131#endif133BOOST_TEST_MESSAGE("\nExpect GetAddedNodeInfo to return expected number of peers with `include_connected` true/false");134BOOST_CHECK_EQUAL(connman->GetAddedNodeInfo(/*include_connected=*/true).size(), nodes.size());135BOOST_CHECK(connman->GetAddedNodeInfo(/*include_connected=*/false).empty());137// Test AddedNodesContain()138for (auto node : connman->TestNodes()) {139BOOST_CHECK(connman->AddedNodesContain(node->addr));140}141AddPeer(id, nodes, *peerman, *connman, ConnectionType::OUTBOUND_FULL_RELAY);142BOOST_CHECK(!connman->AddedNodesContain(nodes.back()->addr));144BOOST_TEST_MESSAGE("\nPrint GetAddedNodeInfo contents:");145for (const auto& info : connman->GetAddedNodeInfo(/*include_connected=*/true)) {146BOOST_TEST_MESSAGE(strprintf("\nadded node: %s", info.m_params.m_added_node));147BOOST_TEST_MESSAGE(strprintf("connected: %s", info.fConnected));148if (info.fConnected) {149BOOST_TEST_MESSAGE(strprintf("IP address: %s", info.resolvedAddress.ToStringAddrPort()));150BOOST_TEST_MESSAGE(strprintf("direction: %s", info.fInbound ? "inbound" : "outbound"));151}152}154BOOST_TEST_MESSAGE("\nCheck that all connected peers are correctly detected as connected");155for (const auto& node : connman->TestNodes()) {156BOOST_CHECK(connman->AlreadyConnectedToAddressPublic(node->addr));157}159// Clean up160for (auto node : connman->TestNodes()) {161peerman->FinalizeNode(*node);162}163connman->ClearTestNodes();164}166BOOST_AUTO_TEST_SUITE_END()
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.