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.
752g_reachable_nets.RemoveAll();754BOOST_CHECK(!g_reachable_nets.Contains(NET_UNROUTABLE));755BOOST_CHECK(!g_reachable_nets.Contains(NET_INTERNAL));757g_reachable_nets.Add(NET_IPV4);758g_reachable_nets.Add(NET_IPV6);759g_reachable_nets.Add(NET_ONION);760g_reachable_nets.Add(NET_I2P);761g_reachable_nets.Add(NET_CJDNS);762g_reachable_nets.Add(NET_UNROUTABLE);763g_reachable_nets.Add(NET_INTERNAL);764}766CNetAddr UtilBuildAddress(unsigned char p1, unsigned char p2, unsigned char p3, unsigned char p4)767{768unsigned char ip[] = {p1, p2, p3, p4};770struct sockaddr_in sa;771memset(&sa, 0, sizeof(sockaddr_in)); // initialize the memory block772memcpy(&(sa.sin_addr), &ip, sizeof(ip));773return CNetAddr(sa.sin_addr);774}777BOOST_AUTO_TEST_CASE(LimitedAndReachable_CNetAddr)778{779CNetAddr addr = UtilBuildAddress(0x001, 0x001, 0x001, 0x001); // 1.1.1.1781g_reachable_nets.Add(NET_IPV4);782BOOST_CHECK(g_reachable_nets.Contains(addr));784g_reachable_nets.Remove(NET_IPV4);785BOOST_CHECK(!g_reachable_nets.Contains(addr));787g_reachable_nets.Add(NET_IPV4); // have to reset this, because this is stateful.788}791BOOST_AUTO_TEST_CASE(LocalAddress_BasicLifecycle)792{793CService addr = CService(UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000); // 2.1.1.1:1000795g_reachable_nets.Add(NET_IPV4);797BOOST_CHECK(!IsLocal(addr));798BOOST_CHECK(AddLocal(addr, 1000));799BOOST_CHECK(IsLocal(addr));801RemoveLocal(addr);802BOOST_CHECK(!IsLocal(addr));803}805BOOST_AUTO_TEST_CASE(LocalAddress_nScore_Overflow)806{807g_reachable_nets.Add(NET_IPV4);808const CService addr{UtilBuildAddress(0x002, 0x001, 0x001, 0x001), 1000}; // 2.1.1.1:1000810const auto get_score = [](const CService& service) -> int {811LOCK(g_maplocalhost_mutex);812const auto it = mapLocalHost.find(service);813return it != mapLocalHost.end() ? it->second.nScore : 0;814};816const int initial_score = 1000;817BOOST_REQUIRE(AddLocal(addr, initial_score));818BOOST_REQUIRE(IsLocal(addr));819BOOST_CHECK_EQUAL(get_score(addr), initial_score);821// SeenLocal should increment nScore by 1.822BOOST_CHECK(SeenLocal(addr));823BOOST_CHECK_EQUAL(get_score(addr), initial_score + 1);825// AddLocal() saturates nScore when updating an existing entry at INT_MAX.826BOOST_REQUIRE(AddLocal(addr, std::numeric_limits<int>::max()));827BOOST_CHECK_EQUAL(get_score(addr), std::numeric_limits<int>::max());829BOOST_CHECK(AddLocal(addr, std::numeric_limits<int>::max()));830BOOST_CHECK_EQUAL(get_score(addr), std::numeric_limits<int>::max());832// SeenLocal() also saturates at INT_MAX.833BOOST_CHECK(SeenLocal(addr));834BOOST_CHECK_EQUAL(get_score(addr), std::numeric_limits<int>::max());836RemoveLocal(addr);837BOOST_CHECK(!IsLocal(addr));838}840BOOST_AUTO_TEST_CASE(initial_advertise_from_version_message)841{842LOCK(NetEventsInterface::g_msgproc_mutex);843auto& connman{static_cast<ConnmanTestMsg&>(*m_node.connman)};845// Tests the following scenario:846// * -bind=3.4.5.6:20001 is specified847// * we make an outbound connection to a peer848// * the peer reports he sees us as 2.3.4.5:20002 in the version message849// (20002 is a random port assigned by our OS for the outgoing TCP connection,850// we cannot accept connections to it)851// * we should self-advertise to that peer as 2.3.4.5:20001853// Pretend that we bound to this port.854const uint16_t bind_port = 20001;855m_node.args->ForceSetArg("-bind", strprintf("3.4.5.6:%u", bind_port));856m_node.connman->SetCaptureMessages(true);858// Our address:port as seen from the peer - 2.3.4.5:20002 (different from the above).859in_addr peer_us_addr;860peer_us_addr.s_addr = htonl(0x02030405);861const CService peer_us{peer_us_addr, 20002};863// Create a peer with a routable IPv4 address.864in_addr peer_in_addr;865peer_in_addr.s_addr = htonl(0x01020304);866CNode peer{/*id=*/0,867/*sock=*/nullptr,868/*addrIn=*/CAddress{CService{peer_in_addr, 8333}, NODE_NETWORK},869/*nKeyedNetGroupIn=*/0,870/*nLocalHostNonceIn=*/0,871/*addrBindIn=*/CService{},872/*addrNameIn=*/std::string{},873/*conn_type_in=*/ConnectionType::OUTBOUND_FULL_RELAY,874/*inbound_onion=*/false,875/*network_key=*/2};877const uint64_t services{NODE_NETWORK | NODE_WITNESS};878const int64_t time{0};880// Force ChainstateManager::IsInitialBlockDownload() to return false.881// Otherwise PushAddress() isn't called by PeerManager::ProcessMessage().882auto& chainman = static_cast<TestChainstateManager&>(*m_node.chainman);883chainman.JumpOutOfIbd();885m_node.peerman->InitializeNode(peer, NODE_NETWORK);887m_node.peerman->SendMessages(peer);888connman.FlushSendBuffer(peer); // Drop sent version message890auto msg_version_receive =891NetMsg::Make(NetMsgType::VERSION, PROTOCOL_VERSION, services, time, services, CAddress::V1_NETWORK(peer_us));892Assert(connman.ReceiveMsgFrom(peer, std::move(msg_version_receive)));893peer.fPauseSend = false;894bool more_work{connman.ProcessMessagesOnce(peer)};895Assert(!more_work);897m_node.peerman->SendMessages(peer);898connman.FlushSendBuffer(peer); // Drop sent verack message900Assert(connman.ReceiveMsgFrom(peer, NetMsg::Make(NetMsgType::VERACK)));901peer.fPauseSend = false;902// Will set peer.fSuccessfullyConnected to true (necessary in SendMessages()).903more_work = connman.ProcessMessagesOnce(peer);904Assert(!more_work);906// Ensure that peer_us_addr:bind_port is sent to the peer.907const CService expected{peer_us_addr, bind_port};908bool sent{false};910const auto CaptureMessageOrig = CaptureMessage;911CaptureMessage = [&sent, &expected](const CAddress& addr,912const std::string& msg_type,913std::span<const unsigned char> data,914bool is_incoming) -> void {915if (!is_incoming && msg_type == "addr") {916std::vector<CAddress> addresses;918SpanReader{data} >> CAddress::V1_NETWORK(addresses);920for (const auto& addr : addresses) {921if (addr == expected) {922sent = true;923return;924}925}926}927};929m_node.peerman->SendMessages(peer);931BOOST_CHECK(sent);933CaptureMessage = CaptureMessageOrig;934chainman.ResetIbd();935m_node.connman->SetCaptureMessages(false);936m_node.args->ForceSetArg("-bind", "");937}940BOOST_AUTO_TEST_CASE(advertise_local_address)941{942auto CreatePeer = [](const CAddress& addr) {943return std::make_unique<CNode>(/*id=*/0,944/*sock=*/nullptr,945addr,946/*nKeyedNetGroupIn=*/0,947/*nLocalHostNonceIn=*/0,948CAddress{},949/*pszDest=*/std::string{},950ConnectionType::OUTBOUND_FULL_RELAY,951/*inbound_onion=*/false,952/*network_key=*/0);953};954g_reachable_nets.Add(NET_CJDNS);956CAddress addr_ipv4{Lookup("1.2.3.4", 8333, false).value(), NODE_NONE};957BOOST_REQUIRE(addr_ipv4.IsValid());958BOOST_REQUIRE(addr_ipv4.IsIPv4());960CAddress addr_ipv6{Lookup("1122:3344:5566:7788:9900:aabb:ccdd:eeff", 8333, false).value(), NODE_NONE};961BOOST_REQUIRE(addr_ipv6.IsValid());962BOOST_REQUIRE(addr_ipv6.IsIPv6());964CAddress addr_ipv6_tunnel{Lookup("2002:3344:5566:7788:9900:aabb:ccdd:eeff", 8333, false).value(), NODE_NONE};965BOOST_REQUIRE(addr_ipv6_tunnel.IsValid());966BOOST_REQUIRE(addr_ipv6_tunnel.IsIPv6());967BOOST_REQUIRE(addr_ipv6_tunnel.IsRFC3964());969CAddress addr_teredo{Lookup("2001:0000:5566:7788:9900:aabb:ccdd:eeff", 8333, false).value(), NODE_NONE};970BOOST_REQUIRE(addr_teredo.IsValid());971BOOST_REQUIRE(addr_teredo.IsIPv6());972BOOST_REQUIRE(addr_teredo.IsRFC4380());974CAddress addr_onion;975BOOST_REQUIRE(addr_onion.SetSpecial("pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion"));976BOOST_REQUIRE(addr_onion.IsValid());977BOOST_REQUIRE(addr_onion.IsTor());979CAddress addr_i2p;980BOOST_REQUIRE(addr_i2p.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p"));981BOOST_REQUIRE(addr_i2p.IsValid());982BOOST_REQUIRE(addr_i2p.IsI2P());984CService service_cjdns{Lookup("fc00:3344:5566:7788:9900:aabb:ccdd:eeff", 8333, false).value(), NODE_NONE};985CAddress addr_cjdns{MaybeFlipIPv6toCJDNS(service_cjdns), NODE_NONE};986BOOST_REQUIRE(addr_cjdns.IsValid());987BOOST_REQUIRE(addr_cjdns.IsCJDNS());989const auto peer_ipv4{CreatePeer(addr_ipv4)};990const auto peer_ipv6{CreatePeer(addr_ipv6)};991const auto peer_ipv6_tunnel{CreatePeer(addr_ipv6_tunnel)};992const auto peer_teredo{CreatePeer(addr_teredo)};993const auto peer_onion{CreatePeer(addr_onion)};994const auto peer_i2p{CreatePeer(addr_i2p)};995const auto peer_cjdns{CreatePeer(addr_cjdns)};997// one local clearnet address - advertise to all but privacy peers998AddLocal(addr_ipv4);999BOOST_CHECK(GetLocalAddress(*peer_ipv4) == addr_ipv4);1000BOOST_CHECK(GetLocalAddress(*peer_ipv6) == addr_ipv4);
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.