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.
1002// Collision between 36 and 19.1003CService addr = ResolveService("250.1.1.36");1004BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));1005BOOST_CHECK(!addrman->Good(addr));1007auto info = addrman->SelectTriedCollision().first;1008BOOST_CHECK_EQUAL(info.ToStringAddrPort(), "250.1.1.19:0");1010// Ensure test of address fails, so that it is evicted.1011// Update entry in tried by setting last good connection in the deep past.1012BOOST_CHECK(!addrman->Good(info, NodeSeconds{1s}));1013addrman->Attempt(info, /*fCountFailure=*/false, Now<NodeSeconds>() - 61s);1015// Should swap 36 for 19.1016addrman->ResolveCollisions();1017BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");1018AddressPosition addr_pos{addrman->FindAddressEntry(CAddress(addr, NODE_NONE)).value()};1019BOOST_CHECK(addr_pos.tried);1021// If 36 was swapped for 19, then adding 36 to tried should fail because we1022// are attempting to add a duplicate.1023// We check this by verifying Good() returns false and also verifying that1024// we have no collisions.1025BOOST_CHECK(!addrman->Good(addr));1026BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");1028// 19 should fail as a collision (not a duplicate) if we now attempt to move1029// it to the tried table.1030CService addr19 = ResolveService("250.1.1.19");1031BOOST_CHECK(!addrman->Good(addr19));1032BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.36:0");1034// Eviction is also successful if too much time has passed since last try1035FakeNodeClock clock{};1036clock += 4h;1037addrman->ResolveCollisions();1038BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");1039//Now 19 is in tried again, and 36 back to new1040AddressPosition addr_pos19{addrman->FindAddressEntry(CAddress(addr19, NODE_NONE)).value()};1041BOOST_CHECK(addr_pos19.tried);1042AddressPosition addr_pos36{addrman->FindAddressEntry(CAddress(addr, NODE_NONE)).value()};1043BOOST_CHECK(!addr_pos36.tried);1044}1046static auto AddrmanToStream(const AddrMan& addrman)1047{1048DataStream ssPeersIn{};1049ssPeersIn << Params().MessageStart();1050ssPeersIn << addrman;1051return ssPeersIn;1052}1054BOOST_AUTO_TEST_CASE(load_addrman)1055{1056AddrMan addrman{EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node)};1058std::optional<CService> addr1, addr2, addr3, addr4;1059addr1 = Lookup("250.7.1.1", 8333, false);1060BOOST_CHECK(addr1.has_value());1061addr2 = Lookup("250.7.2.2", 9999, false);1062BOOST_CHECK(addr2.has_value());1063addr3 = Lookup("250.7.3.3", 9999, false);1064BOOST_CHECK(addr3.has_value());1065addr3 = Lookup("250.7.3.3"s, 9999, false);1066BOOST_CHECK(addr3.has_value());1067addr4 = Lookup("250.7.3.3\0example.com"s, 9999, false);1068BOOST_CHECK(!addr4.has_value());1070// Add three addresses to new table.1071const std::optional<CService> source{Lookup("252.5.1.1", 8333, false)};1072BOOST_CHECK(source.has_value());1073std::vector<CAddress> addresses{CAddress(addr1.value(), NODE_NONE), CAddress(addr2.value(), NODE_NONE), CAddress(addr3.value(), NODE_NONE)};1074BOOST_CHECK(addrman.Add(addresses, source.value()));1075BOOST_CHECK(addrman.Size() == 3);1077// Test that the de-serialization does not throw an exception.1078auto ssPeers1{AddrmanToStream(addrman)};1079AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};1081BOOST_CHECK(addrman1.Size() == 0);1082{1083unsigned char pchMsgTmp[4];1084BOOST_CHECK_NO_THROW(ssPeers1 >> pchMsgTmp >> addrman1);1085}1087BOOST_CHECK(addrman1.Size() == 3);1089// Test that ReadFromStream creates an addrman with the correct number of addrs.1090DataStream ssPeers2 = AddrmanToStream(addrman);1092AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};1093BOOST_CHECK(addrman2.Size() == 0);1094ReadFromStream(addrman2, ssPeers2);1095BOOST_CHECK(addrman2.Size() == 3);1096}1098// Produce a corrupt peers.dat that claims 20 addrs when it only has one addr.1099static auto MakeCorruptPeersDat()1100{1101DataStream s{};1102s << ::Params().MessageStart();1104unsigned char nVersion = 1;1105s << nVersion;1106s << ((unsigned char)32);1107s << uint256::ONE;1108s << 10; // nNew1109s << 10; // nTried1111int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);1112s << nUBuckets;1114const std::optional<CService> serv{Lookup("252.1.1.1", 7777, false)};1115BOOST_REQUIRE(serv.has_value());1116CAddress addr = CAddress(serv.value(), NODE_NONE);1117std::optional<CNetAddr> resolved{LookupHost("252.2.2.2", false)};1118BOOST_REQUIRE(resolved.has_value());1119AddrInfo info = AddrInfo(addr, resolved.value());1120s << CAddress::V1_DISK(info);1122return s;1123}1125BOOST_AUTO_TEST_CASE(load_addrman_corrupted)1126{1127// Test that the de-serialization of corrupted peers.dat throws an exception.1128auto ssPeers1{MakeCorruptPeersDat()};1129AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};1130BOOST_CHECK(addrman1.Size() == 0);1131BOOST_CHECK_EXCEPTION([&]1132{1133unsigned char pchMsgTmp[4];1134ssPeers1 >> pchMsgTmp;1135ssPeers1 >> addrman1;1136}(), std::ios_base::failure, HasReason{"end of data"});1138// Test that ReadFromStream fails if peers.dat is corrupt1139auto ssPeers2{MakeCorruptPeersDat()};1141AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};1142BOOST_CHECK(addrman2.Size() == 0);1143BOOST_CHECK_THROW(ReadFromStream(addrman2, ssPeers2), std::ios_base::failure);1144}1146BOOST_AUTO_TEST_CASE(addrman_update_address)1147{1148// Tests updating nTime via Connected() and nServices via SetServices() and Add()1149auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));1150CNetAddr source{ResolveIP("252.2.2.2")};1151CAddress addr{CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE)};1153const auto start_time{Now<NodeSeconds>() - 10000s};1154addr.nTime = start_time;1155BOOST_CHECK(addrman->Add({addr}, source));1156BOOST_CHECK_EQUAL(addrman->Size(), 1U);1158// Updating an addrman entry with a different port doesn't change it1159CAddress addr_diff_port{CAddress(ResolveService("250.1.1.1", 8334), NODE_NONE)};1160addr_diff_port.nTime = start_time;1161addrman->Connected(addr_diff_port);1162addrman->SetServices(addr_diff_port, NODE_NETWORK_LIMITED);1163std::vector<CAddress> vAddr1{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};1164BOOST_CHECK_EQUAL(vAddr1.size(), 1U);1165BOOST_CHECK(vAddr1.at(0).nTime == start_time);1166BOOST_CHECK_EQUAL(vAddr1.at(0).nServices, NODE_NONE);1168// Updating an addrman entry with the correct port is successful1169addrman->Connected(addr);1170addrman->SetServices(addr, NODE_NETWORK_LIMITED);1171std::vector<CAddress> vAddr2 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);1172BOOST_CHECK_EQUAL(vAddr2.size(), 1U);1173BOOST_CHECK(vAddr2.at(0).nTime >= start_time + 10000s);1174BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);1176// Updating an existing addr through Add() (used in gossip relay) can add additional services but can't remove existing ones.1177CAddress addr_v2{CAddress(ResolveService("250.1.1.1", 8333), NODE_P2P_V2)};1178addr_v2.nTime = start_time;1179BOOST_CHECK(!addrman->Add({addr_v2}, source));1180std::vector<CAddress> vAddr3{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};1181BOOST_CHECK_EQUAL(vAddr3.size(), 1U);1182BOOST_CHECK_EQUAL(vAddr3.at(0).nServices, NODE_P2P_V2 | NODE_NETWORK_LIMITED);1184// SetServices() (used when we connected to them) overwrites existing service flags1185addrman->SetServices(addr, NODE_NETWORK);1186std::vector<CAddress> vAddr4{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};1187BOOST_CHECK_EQUAL(vAddr4.size(), 1U);1188BOOST_CHECK_EQUAL(vAddr4.at(0).nServices, NODE_NETWORK);1190// Promoting to Tried does not affect the service flags1191BOOST_CHECK(addrman->Good(addr)); // addr has NODE_NONE1192std::vector<CAddress> vAddr5{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};1193BOOST_CHECK_EQUAL(vAddr5.size(), 1U);1194BOOST_CHECK_EQUAL(vAddr5.at(0).nServices, NODE_NETWORK);1196// Adding service flags even works when the addr is in Tried1197BOOST_CHECK(!addrman->Add({addr_v2}, source));1198std::vector<CAddress> vAddr6{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};1199BOOST_CHECK_EQUAL(vAddr6.size(), 1U);1200BOOST_CHECK_EQUAL(vAddr6.at(0).nServices, NODE_NETWORK | NODE_P2P_V2);1201}1203BOOST_AUTO_TEST_CASE(addrman_size)1204{1205auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));1206const CNetAddr source = ResolveIP("252.2.2.2");1208// empty addrman1209BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 0U);1210BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 0U);1211BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 0U);1212BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 0U);1214// add two ipv4 addresses, one to tried and new1215const CAddress addr1{ResolveService("250.1.1.1", 8333), NODE_NONE};1216BOOST_CHECK(addrman->Add({addr1}, source));1217BOOST_CHECK(addrman->Good(addr1));1218const CAddress addr2{ResolveService("250.1.1.2", 8333), NODE_NONE};1219BOOST_CHECK(addrman->Add({addr2}, source));1221BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 2U);1222BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);1223BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 1U);1224BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);1225BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/true), 1U);1226BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 1U);1228// add one i2p address to new1229CService i2p_addr;1230i2p_addr.SetSpecial("UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P");1231const CAddress addr3{i2p_addr, NODE_NONE};1232BOOST_CHECK(addrman->Add({addr3}, source));1233BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 3U);1234BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);1235BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/std::nullopt), 1U);1236BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/true), 1U);1237BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 2U);1238BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);1239}1241BOOST_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.