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.
1001return AddressPosition(/*tried_in=*/false,1002/*multiplicity_in=*/addr_info->nRefCount,1003/*bucket_in=*/bucket,1004/*position_in=*/addr_info->GetBucketPosition(nKey, true, bucket));1005}1006}1008size_t AddrManImpl::Size_(std::optional<Network> net, std::optional<bool> in_new) const1009{1010AssertLockHeld(cs);1012if (!net.has_value()) {1013if (in_new.has_value()) {1014return *in_new ? nNew : nTried;1015} else {1016return vRandom.size();1017}1018}1019if (auto it = m_network_counts.find(*net); it != m_network_counts.end()) {1020auto net_count = it->second;1021if (in_new.has_value()) {1022return *in_new ? net_count.n_new : net_count.n_tried;1023} else {1024return net_count.n_new + net_count.n_tried;1025}1026}1027return 0;1028}1030void AddrManImpl::Check() const1031{1032AssertLockHeld(cs);1034// Run consistency checks 1 in m_consistency_check_ratio times if enabled1035if (m_consistency_check_ratio == 0) return;1036if (insecure_rand.randrange(m_consistency_check_ratio) >= 1) return;1038const int err{CheckAddrman()};1039if (err) {1040LogError("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i", err);1041assert(false);1042}1043}1045int AddrManImpl::CheckAddrman() const1046{1047AssertLockHeld(cs);1049LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE(1050strprintf("new %i, tried %i, total %u", nNew, nTried, vRandom.size()), BCLog::ADDRMAN);1052std::unordered_set<nid_type> setTried;1053std::unordered_map<nid_type, int> mapNew;1054std::unordered_map<Network, NewTriedCount> local_counts;1056if (vRandom.size() != (size_t)(nTried + nNew))1057return -7;1059for (const auto& entry : mapInfo) {1060nid_type n = entry.first;1061const AddrInfo& info = entry.second;1062if (info.fInTried) {1063if (!TicksSinceEpoch<std::chrono::seconds>(info.m_last_success)) {1064return -1;1065}1066if (info.nRefCount)1067return -2;1068setTried.insert(n);1069local_counts[info.GetNetwork()].n_tried++;1070} else {1071if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS)1072return -3;1073if (!info.nRefCount)1074return -4;1075mapNew[n] = info.nRefCount;1076local_counts[info.GetNetwork()].n_new++;1077}1078const auto it{mapAddr.find(info)};1079if (it == mapAddr.end() || it->second != n) {1080return -5;1081}1082if (info.nRandomPos < 0 || (size_t)info.nRandomPos >= vRandom.size() || vRandom[info.nRandomPos] != n)1083return -14;1084if (info.m_last_try < NodeSeconds{0s}) {1085return -6;1086}1087if (info.m_last_success < NodeSeconds{0s}) {1088return -8;1089}1090}1092if (setTried.size() != (size_t)nTried)1093return -9;1094if (mapNew.size() != (size_t)nNew)1095return -10;1097for (int n = 0; n < ADDRMAN_TRIED_BUCKET_COUNT; n++) {1098for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {1099if (vvTried[n][i] != -1) {1100if (!setTried.contains(vvTried[n][i]))1101return -11;1102const auto it{mapInfo.find(vvTried[n][i])};1103if (it == mapInfo.end() || it->second.GetTriedBucket(nKey, m_netgroupman) != n) {1104return -17;1105}1106if (it->second.GetBucketPosition(nKey, false, n) != i) {1107return -18;1108}1109setTried.erase(vvTried[n][i]);1110}1111}1112}1114for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {1115for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {1116if (vvNew[n][i] != -1) {1117if (!mapNew.contains(vvNew[n][i]))1118return -12;1119const auto it{mapInfo.find(vvNew[n][i])};1120if (it == mapInfo.end() || it->second.GetBucketPosition(nKey, true, n) != i) {1121return -19;1122}1123if (--mapNew[vvNew[n][i]] == 0)1124mapNew.erase(vvNew[n][i]);1125}1126}1127}1129if (setTried.size())1130return -13;1131if (mapNew.size())1132return -15;1133if (nKey.IsNull())1134return -16;1136// It's possible that m_network_counts may have all-zero entries that local_counts1137// doesn't have if addrs from a network were being added and then removed again in the past.1138if (m_network_counts.size() < local_counts.size()) {1139return -20;1140}1141for (const auto& [net, count] : m_network_counts) {1142if (local_counts[net].n_new != count.n_new || local_counts[net].n_tried != count.n_tried) {1143return -21;1144}1145}1147return 0;1148}1150size_t AddrManImpl::Size(std::optional<Network> net, std::optional<bool> in_new) const1151{1152LOCK(cs);1153Check();1154auto ret = Size_(net, in_new);1155Check();1156return ret;1157}1159bool AddrManImpl::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)1160{1161LOCK(cs);1162Check();1163auto ret = Add_(vAddr, source, time_penalty);1164Check();1165return ret;1166}1168bool AddrManImpl::Good(const CService& addr, NodeSeconds time)1169{1170LOCK(cs);1171Check();1172auto ret = Good_(addr, /*test_before_evict=*/true, time);1173Check();1174return ret;1175}1177void AddrManImpl::Attempt(const CService& addr, bool fCountFailure, NodeSeconds time)1178{1179LOCK(cs);1180Check();1181Attempt_(addr, fCountFailure, time);1182Check();1183}1185void AddrManImpl::ResolveCollisions()1186{1187LOCK(cs);1188Check();1189ResolveCollisions_();1190Check();1191}1193std::pair<CAddress, NodeSeconds> AddrManImpl::SelectTriedCollision()1194{1195LOCK(cs);1196Check();1197auto ret = SelectTriedCollision_();1198Check();1199return ret;1200}1202std::pair<CAddress, NodeSeconds> AddrManImpl::Select(bool new_only, const std::unordered_set<Network>& networks) const1203{1204LOCK(cs);1205Check();1206auto addrRet = Select_(new_only, networks);1207Check();1208return addrRet;1209}1211std::vector<CAddress> AddrManImpl::GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network, const bool filtered) const1212{1213LOCK(cs);1214Check();1215auto addresses = GetAddr_(max_addresses, max_pct, network, filtered);1216Check();1217return addresses;1218}1220std::vector<std::pair<AddrInfo, AddressPosition>> AddrManImpl::GetEntries(bool from_tried) const1221{1222LOCK(cs);1223Check();1224auto addrInfos = GetEntries_(from_tried);1225Check();1226return addrInfos;1227}1229void AddrManImpl::Connected(const CService& addr, NodeSeconds time)1230{1231LOCK(cs);1232Check();1233Connected_(addr, time);1234Check();1235}1237void AddrManImpl::SetServices(const CService& addr, ServiceFlags nServices)1238{1239LOCK(cs);1240Check();1241SetServices_(addr, nServices);1242Check();1243}1245std::optional<AddressPosition> AddrManImpl::FindAddressEntry(const CAddress& addr)1246{1247LOCK(cs);1248Check();1249auto entry = FindAddressEntry_(addr);1250Check();