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.
252// Select pulls from new and tried regardless of port number.253std::set<uint16_t> ports;254for (int i = 0; i < 20; ++i) {255ports.insert(addrman->Select().first.GetPort());256}257BOOST_CHECK_EQUAL(ports.size(), 3U);258}260BOOST_AUTO_TEST_CASE(addrman_select_by_network)261{262auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));263BOOST_CHECK(!addrman->Select(/*new_only=*/true, {NET_IPV4}).first.IsValid());264BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_IPV4}).first.IsValid());266// add ipv4 address to the new table267CNetAddr source = ResolveIP("252.2.2.2");268CService addr1 = ResolveService("250.1.1.1", 8333);269BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));271BOOST_CHECK(addrman->Select(/*new_only=*/true, {NET_IPV4}).first == addr1);272BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_IPV4}).first == addr1);273BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_IPV6}).first.IsValid());274BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_ONION}).first.IsValid());275BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_I2P}).first.IsValid());276BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_CJDNS}).first.IsValid());277BOOST_CHECK(!addrman->Select(/*new_only=*/true, {NET_CJDNS}).first.IsValid());278BOOST_CHECK(addrman->Select(/*new_only=*/false).first == addr1);280// add I2P address to the new table281CAddress i2p_addr;282i2p_addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");283BOOST_CHECK(addrman->Add({i2p_addr}, source));285BOOST_CHECK(addrman->Select(/*new_only=*/true, {NET_I2P}).first == i2p_addr);286BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_I2P}).first == i2p_addr);287BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_IPV4}).first == addr1);288std::unordered_set<Network> nets_with_entries = {NET_IPV4, NET_I2P};289BOOST_CHECK(addrman->Select(/*new_only=*/false, nets_with_entries).first.IsValid());290BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_IPV6}).first.IsValid());291BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_ONION}).first.IsValid());292BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_CJDNS}).first.IsValid());293std::unordered_set<Network> nets_without_entries = {NET_IPV6, NET_ONION, NET_CJDNS};294BOOST_CHECK(!addrman->Select(/*new_only=*/false, nets_without_entries).first.IsValid());296// bump I2P address to tried table297BOOST_CHECK(addrman->Good(i2p_addr));299BOOST_CHECK(!addrman->Select(/*new_only=*/true, {NET_I2P}).first.IsValid());300BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_I2P}).first == i2p_addr);302// add another I2P address to the new table303CAddress i2p_addr2;304i2p_addr2.SetSpecial("c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p");305BOOST_CHECK(addrman->Add({i2p_addr2}, source));307BOOST_CHECK(addrman->Select(/*new_only=*/true, {NET_I2P}).first == i2p_addr2);309// ensure that both new and tried table are selected from310bool new_selected{false};311bool tried_selected{false};312int counter = 256;314while (--counter > 0 && (!new_selected || !tried_selected)) {315const CAddress selected{addrman->Select(/*new_only=*/false, {NET_I2P}).first};316BOOST_REQUIRE(selected == i2p_addr || selected == i2p_addr2);317if (selected == i2p_addr) {318tried_selected = true;319} else {320new_selected = true;321}322}324BOOST_CHECK(new_selected);325BOOST_CHECK(tried_selected);326}328BOOST_AUTO_TEST_CASE(addrman_select_special)329{330// use a non-deterministic addrman to ensure a passing test isn't due to setup331auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, /*deterministic=*/false, GetCheckRatio(m_node));333CNetAddr source = ResolveIP("252.2.2.2");335// add I2P address to the tried table336CAddress i2p_addr;337i2p_addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");338BOOST_CHECK(addrman->Add({i2p_addr}, source));339BOOST_CHECK(addrman->Good(i2p_addr));341// add ipv4 address to the new table342CService addr1 = ResolveService("250.1.1.3", 8333);343BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));345// since the only ipv4 address is on the new table, ensure that the new346// table gets selected even if new_only is false. if the table was being347// selected at random, this test will sporadically fail348BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_IPV4}).first == addr1);349}351BOOST_AUTO_TEST_CASE(addrman_new_collisions)352{353auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));355CNetAddr source = ResolveIP("252.2.2.2");357uint32_t num_addrs{0};359BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);361while (num_addrs < 22) { // Magic number! 250.1.1.1 - 250.1.1.22 do not collide with deterministic key = 1362CService addr = ResolveService("250.1.1." + ToString(++num_addrs));363BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));365// Test: No collision in new table yet.366BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);367}369// Test: new table collision!370CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));371uint32_t collisions{1};372BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));373BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);375CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));376BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));377BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);378}380BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)381{382auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));383CAddress addr{CAddress(ResolveService("253.3.3.3", 8333), NODE_NONE)};384const auto start_time{Now<NodeSeconds>()};385addr.nTime = start_time;387// test that multiplicity stays at 1 if nTime doesn't increase388for (unsigned int i = 1; i < 20; ++i) {389std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};390CNetAddr source{ResolveIP(addr_ip)};391addrman->Add({addr}, source);392}393AddressPosition addr_pos = addrman->FindAddressEntry(addr).value();394BOOST_CHECK_EQUAL(addr_pos.multiplicity, 1U);395BOOST_CHECK_EQUAL(addrman->Size(), 1U);397// if nTime increases, an addr can occur in up to 8 buckets398// The acceptance probability decreases exponentially with existing multiplicity -399// choose number of iterations such that it gets to 8 with deterministic addrman.400for (unsigned int i = 1; i < 400; ++i) {401std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};402CNetAddr source{ResolveIP(addr_ip)};403addr.nTime = start_time + std::chrono::seconds{i};404addrman->Add({addr}, source);405}406AddressPosition addr_pos_multi = addrman->FindAddressEntry(addr).value();407BOOST_CHECK_EQUAL(addr_pos_multi.multiplicity, 8U);408// multiplicity doesn't affect size409BOOST_CHECK_EQUAL(addrman->Size(), 1U);410}412BOOST_AUTO_TEST_CASE(addrman_tried_collisions)413{414auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));416CNetAddr source = ResolveIP("252.2.2.2");418uint32_t num_addrs{0};420BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);422while (num_addrs < 35) { // Magic number! 250.1.1.1 - 250.1.1.35 do not collide in tried with deterministic key = 1423CService addr = ResolveService("250.1.1." + ToString(++num_addrs));424BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));426// Test: Add to tried without collision427BOOST_CHECK(addrman->Good(CAddress(addr, NODE_NONE)));429}431// Test: Unable to add to tried table due to collision!432CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));433BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));434BOOST_CHECK(!addrman->Good(CAddress(addr1, NODE_NONE)));436// Test: Add the next address to tried without collision437CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));438BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));439BOOST_CHECK(addrman->Good(CAddress(addr2, NODE_NONE)));440}443BOOST_AUTO_TEST_CASE(addrman_getaddr)444{445auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));447// Test: Sanity check, GetAddr should never return anything if addrman448// is empty.449BOOST_CHECK_EQUAL(addrman->Size(), 0U);450std::vector<CAddress> vAddr1 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);451BOOST_CHECK_EQUAL(vAddr1.size(), 0U);453CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);454addr1.nTime = Now<NodeSeconds>(); // Set time so isTerrible = false455CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);456addr2.nTime = Now<NodeSeconds>();457CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);458addr3.nTime = Now<NodeSeconds>();459CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);460addr4.nTime = Now<NodeSeconds>();461CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);462addr5.nTime = Now<NodeSeconds>();463CNetAddr source1 = ResolveIP("250.1.2.1");464CNetAddr source2 = ResolveIP("250.2.3.3");466// Test: Ensure GetAddr works with new addresses.467BOOST_CHECK(addrman->Add({addr1, addr3, addr5}, source1));468BOOST_CHECK(addrman->Add({addr2, addr4}, source2));470BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 5U);471// Net processing asks for 23% of addresses. 23% of 5 is 1 rounded down.472BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt).size(), 1U);474// Test: Ensure GetAddr works with new and tried addresses.475BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));476BOOST_CHECK(addrman->Good(CAddress(addr2, NODE_NONE)));477BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 5U);478BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt).size(), 1U);480// Test: Ensure GetAddr still returns 23% when addrman has many addrs.481for (unsigned int i = 1; i < (8 * 256); i++) {482int octet1 = i % 256;483int octet2 = i >> 8 % 256;484std::string strAddr = ToString(octet1) + "." + ToString(octet2) + ".1.23";485CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);487// Ensure that for all addrs in addrman, isTerrible == false.488addr.nTime = Now<NodeSeconds>();489addrman->Add({addr}, ResolveIP(strAddr));490if (i % 8 == 0)491addrman->Good(addr);492}493std::vector<CAddress> vAddr = addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt);495size_t percent23 = (addrman->Size() * 23) / 100;496BOOST_CHECK_EQUAL(vAddr.size(), percent23);497BOOST_CHECK_EQUAL(vAddr.size(), 461U);498// (addrman.Size() < number of addresses added) due to address collisions.499BOOST_CHECK_EQUAL(addrman->Size(), 2006U);500}
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.