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.
751// Test: IP addresses in the same /16 prefix752// usually map to the same bucket.753BOOST_CHECK_EQUAL(buckets.size(), 1U);755buckets.clear();756for (int j = 0; j < 4 * 255; j++) {757AddrInfo infoj = AddrInfo(CAddress(758ResolveService(759ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),760ResolveIP("251.4.1.1"));761int bucket = infoj.GetNewBucket(nKey1, ngm_asmap);762buckets.insert(bucket);763}764// Test: IP addresses in the same source /16 prefix should not map to more765// than 64 buckets.766BOOST_CHECK(buckets.size() <= 64);768buckets.clear();769for (int p = 0; p < 255; p++) {770AddrInfo infoj = AddrInfo(771CAddress(ResolveService("250.1.1.1"), NODE_NONE),772ResolveIP("101." + ToString(p) + ".1.1"));773int bucket = infoj.GetNewBucket(nKey1, ngm_asmap);774buckets.insert(bucket);775}776// Test: IP addresses in the different source /16 prefixes usually map to MORE777// than 1 bucket.778BOOST_CHECK(buckets.size() > 1);780buckets.clear();781for (int p = 0; p < 255; p++) {782AddrInfo infoj = AddrInfo(783CAddress(ResolveService("250.1.1.1"), NODE_NONE),784ResolveIP("250." + ToString(p) + ".1.1"));785int bucket = infoj.GetNewBucket(nKey1, ngm_asmap);786buckets.insert(bucket);787}788// Test: IP addresses in the different source /16 prefixes sometimes map to NO MORE789// than 1 bucket.790BOOST_CHECK(buckets.size() == 1);791}793BOOST_AUTO_TEST_CASE(addrman_serialization)794{795auto netgroupman{NetGroupManager::WithEmbeddedAsmap(test::data::asmap)};797const auto ratio = GetCheckRatio(m_node);798auto addrman_asmap1 = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);799auto addrman_asmap1_dup = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);800auto addrman_noasmap = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, ratio);802DataStream stream{};804CAddress addr = CAddress(ResolveService("250.1.1.1"), NODE_NONE);805CNetAddr default_source;807addrman_asmap1->Add({addr}, default_source);809stream << *addrman_asmap1;810// serizalizing/deserializing addrman with the same asmap811stream >> *addrman_asmap1_dup;813AddressPosition addr_pos1 = addrman_asmap1->FindAddressEntry(addr).value();814AddressPosition addr_pos2 = addrman_asmap1_dup->FindAddressEntry(addr).value();815BOOST_CHECK(addr_pos1.multiplicity != 0);816BOOST_CHECK(addr_pos2.multiplicity != 0);818BOOST_CHECK(addr_pos1 == addr_pos2);820// deserializing asmaped peers.dat to non-asmaped addrman821stream << *addrman_asmap1;822stream >> *addrman_noasmap;823AddressPosition addr_pos3 = addrman_noasmap->FindAddressEntry(addr).value();824BOOST_CHECK(addr_pos3.multiplicity != 0);825BOOST_CHECK(addr_pos1.bucket != addr_pos3.bucket);826BOOST_CHECK(addr_pos1.position != addr_pos3.position);828// deserializing non-asmaped peers.dat to asmaped addrman829addrman_asmap1 = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);830addrman_noasmap = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, ratio);831addrman_noasmap->Add({addr}, default_source);832stream << *addrman_noasmap;833stream >> *addrman_asmap1;835AddressPosition addr_pos4 = addrman_asmap1->FindAddressEntry(addr).value();836BOOST_CHECK(addr_pos4.multiplicity != 0);837BOOST_CHECK(addr_pos4.bucket != addr_pos3.bucket);838BOOST_CHECK(addr_pos4 == addr_pos2);840// used to map to different buckets, now maps to the same bucket.841addrman_asmap1 = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);842addrman_noasmap = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, ratio);843CAddress addr1 = CAddress(ResolveService("250.1.1.1"), NODE_NONE);844CAddress addr2 = CAddress(ResolveService("250.2.1.1"), NODE_NONE);845addrman_noasmap->Add({addr, addr2}, default_source);846AddressPosition addr_pos5 = addrman_noasmap->FindAddressEntry(addr1).value();847AddressPosition addr_pos6 = addrman_noasmap->FindAddressEntry(addr2).value();848BOOST_CHECK(addr_pos5.bucket != addr_pos6.bucket);849stream << *addrman_noasmap;850stream >> *addrman_asmap1;851AddressPosition addr_pos7 = addrman_asmap1->FindAddressEntry(addr1).value();852AddressPosition addr_pos8 = addrman_asmap1->FindAddressEntry(addr2).value();853BOOST_CHECK(addr_pos7.bucket == addr_pos8.bucket);854BOOST_CHECK(addr_pos7.position != addr_pos8.position);855}857BOOST_AUTO_TEST_CASE(remove_invalid)858{859// Confirm that invalid addresses are ignored in unserialization.861auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));862DataStream stream{};864const CAddress new1{ResolveService("5.5.5.5"), NODE_NONE};865const CAddress new2{ResolveService("6.6.6.6"), NODE_NONE};866const CAddress tried1{ResolveService("7.7.7.7"), NODE_NONE};867const CAddress tried2{ResolveService("8.8.8.8"), NODE_NONE};869addrman->Add({new1, tried1, new2, tried2}, CNetAddr{});870addrman->Good(tried1);871addrman->Good(tried2);872BOOST_REQUIRE_EQUAL(addrman->Size(), 4);874stream << *addrman;876const std::string str{stream.str()};877size_t pos;879const char new2_raw[]{6, 6, 6, 6};880const uint8_t new2_raw_replacement[]{0, 0, 0, 0}; // 0.0.0.0 is !IsValid()881pos = str.find(new2_raw, 0, sizeof(new2_raw));882BOOST_REQUIRE(pos != std::string::npos);883BOOST_REQUIRE(pos + sizeof(new2_raw_replacement) <= stream.size());884memcpy(stream.data() + pos, new2_raw_replacement, sizeof(new2_raw_replacement));886const char tried2_raw[]{8, 8, 8, 8};887const uint8_t tried2_raw_replacement[]{255, 255, 255, 255}; // 255.255.255.255 is !IsValid()888pos = str.find(tried2_raw, 0, sizeof(tried2_raw));889BOOST_REQUIRE(pos != std::string::npos);890BOOST_REQUIRE(pos + sizeof(tried2_raw_replacement) <= stream.size());891memcpy(stream.data() + pos, tried2_raw_replacement, sizeof(tried2_raw_replacement));893addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));894stream >> *addrman;895BOOST_CHECK_EQUAL(addrman->Size(), 2);896}898BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)899{900auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));902BOOST_CHECK(addrman->Size() == 0);904// Empty addrman should return blank addrman info.905BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");907// Add twenty two addresses.908CNetAddr source = ResolveIP("252.2.2.2");909for (unsigned int i = 1; i < 23; i++) {910CService addr = ResolveService("250.1.1." + ToString(i));911BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));913// No collisions in tried.914BOOST_CHECK(addrman->Good(addr));915BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");916}918// Ensure Good handles duplicates well.919// If an address is a duplicate, Good will return false but will not count it as a collision.920for (unsigned int i = 1; i < 23; i++) {921CService addr = ResolveService("250.1.1." + ToString(i));923// Unable to add duplicate address to tried table.924BOOST_CHECK(!addrman->Good(addr));926// Verify duplicate address not marked as a collision.927BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");928}929}931BOOST_AUTO_TEST_CASE(addrman_noevict)932{933auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));935// Add 35 addresses.936CNetAddr source = ResolveIP("252.2.2.2");937for (unsigned int i = 1; i < 36; i++) {938CService addr = ResolveService("250.1.1." + ToString(i));939BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));941// No collision yet.942BOOST_CHECK(addrman->Good(addr));943}945// Collision in tried table between 36 and 19.946CService addr36 = ResolveService("250.1.1.36");947BOOST_CHECK(addrman->Add({CAddress(addr36, NODE_NONE)}, source));948BOOST_CHECK(!addrman->Good(addr36));949BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.19:0");951// 36 should be discarded and 19 not evicted.952// This means we keep 19 in the tried table and953// 36 stays in the new table.954addrman->ResolveCollisions();955BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");957// Lets create two collisions.958for (unsigned int i = 37; i < 59; i++) {959CService addr = ResolveService("250.1.1." + ToString(i));960BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));961BOOST_CHECK(addrman->Good(addr));962}964// Cause a collision in the tried table.965CService addr59 = ResolveService("250.1.1.59");966BOOST_CHECK(addrman->Add({CAddress(addr59, NODE_NONE)}, source));967BOOST_CHECK(!addrman->Good(addr59));969BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.10:0");971// Cause a second collision in the new table.972BOOST_CHECK(!addrman->Add({CAddress(addr36, NODE_NONE)}, source));974// 36 still cannot be moved from new to tried due to colliding with 19975BOOST_CHECK(!addrman->Good(addr36));976BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() != "[::]:0");978// Resolve all collisions.979addrman->ResolveCollisions();980BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");981}983BOOST_AUTO_TEST_CASE(addrman_evictionworks)984{985auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));987BOOST_CHECK(addrman->Size() == 0);989// Empty addrman should return blank addrman info.990BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");992// Add 35 addresses993CNetAddr source = ResolveIP("252.2.2.2");994for (unsigned int i = 1; i < 36; i++) {995CService addr = ResolveService("250.1.1." + ToString(i));996BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));998// No collision yet.999BOOST_CHECK(addrman->Good(addr));1000}
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.