@@ -291,6 +291,7 @@ void AddrManImpl::Unserialize(Stream& s_)
291
291
mapAddr[info] = n;
292
292
info.nRandomPos = vRandom.size ();
293
293
vRandom.push_back (n);
294
+ m_network_counts[info.GetNetwork ()].n_new ++;
294
295
}
295
296
nIdCount = nNew;
296
297
@@ -310,6 +311,7 @@ void AddrManImpl::Unserialize(Stream& s_)
310
311
mapAddr[info] = nIdCount;
311
312
vvTried[nKBucket][nKBucketPos] = nIdCount;
312
313
nIdCount++;
314
+ m_network_counts[info.GetNetwork ()].n_tried ++;
313
315
} else {
314
316
nLost++;
315
317
}
@@ -464,6 +466,7 @@ void AddrManImpl::Delete(int nId)
464
466
assert (info.nRefCount == 0 );
465
467
466
468
SwapRandom (info.nRandomPos , vRandom.size () - 1 );
469
+ m_network_counts[info.GetNetwork ()].n_new --;
467
470
vRandom.pop_back ();
468
471
mapAddr.erase (info);
469
472
mapInfo.erase (nId);
@@ -504,6 +507,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
504
507
}
505
508
}
506
509
nNew--;
510
+ m_network_counts[info.GetNetwork ()].n_new --;
507
511
508
512
assert (info.nRefCount == 0 );
509
513
@@ -522,6 +526,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
522
526
infoOld.fInTried = false ;
523
527
vvTried[nKBucket][nKBucketPos] = -1 ;
524
528
nTried--;
529
+ m_network_counts[infoOld.GetNetwork ()].n_tried --;
525
530
526
531
// find which new bucket it belongs to
527
532
int nUBucket = infoOld.GetNewBucket (nKey, m_netgroupman);
@@ -533,6 +538,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
533
538
infoOld.nRefCount = 1 ;
534
539
vvNew[nUBucket][nUBucketPos] = nIdEvict;
535
540
nNew++;
541
+ m_network_counts[infoOld.GetNetwork ()].n_new ++;
536
542
LogPrint (BCLog::ADDRMAN, " Moved %s from tried[%i][%i] to new[%i][%i] to make space\n " ,
537
543
infoOld.ToString (), nKBucket, nKBucketPos, nUBucket, nUBucketPos);
538
544
}
@@ -541,6 +547,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
541
547
vvTried[nKBucket][nKBucketPos] = nId;
542
548
nTried++;
543
549
info.fInTried = true ;
550
+ m_network_counts[info.GetNetwork ()].n_tried ++;
544
551
}
545
552
546
553
bool AddrManImpl::AddSingle (const CAddress& addr, const CNetAddr& source, std::chrono::seconds time_penalty)
@@ -592,6 +599,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, std::c
592
599
pinfo = Create (addr, source, &nId);
593
600
pinfo->nTime = std::max (NodeSeconds{0s}, pinfo->nTime - time_penalty);
594
601
nNew++;
602
+ m_network_counts[pinfo->GetNetwork ()].n_new ++;
595
603
}
596
604
597
605
int nUBucket = pinfo->GetNewBucket (nKey, source, m_netgroupman);
@@ -962,6 +970,28 @@ std::optional<AddressPosition> AddrManImpl::FindAddressEntry_(const CAddress& ad
962
970
}
963
971
}
964
972
973
+ size_t AddrManImpl::Size_ (std::optional<Network> net, std::optional<bool > in_new) const
974
+ {
975
+ AssertLockHeld (cs);
976
+
977
+ if (!net.has_value ()) {
978
+ if (in_new.has_value ()) {
979
+ return *in_new ? nNew : nTried;
980
+ } else {
981
+ return vRandom.size ();
982
+ }
983
+ }
984
+ if (auto it = m_network_counts.find (*net); it != m_network_counts.end ()) {
985
+ auto net_count = it->second ;
986
+ if (in_new.has_value ()) {
987
+ return *in_new ? net_count.n_new : net_count.n_tried ;
988
+ } else {
989
+ return net_count.n_new + net_count.n_tried ;
990
+ }
991
+ }
992
+ return 0 ;
993
+ }
994
+
965
995
void AddrManImpl::Check () const
966
996
{
967
997
AssertLockHeld (cs);
@@ -986,6 +1016,7 @@ int AddrManImpl::CheckAddrman() const
986
1016
987
1017
std::unordered_set<int > setTried;
988
1018
std::unordered_map<int , int > mapNew;
1019
+ std::unordered_map<Network, NewTriedCount> local_counts;
989
1020
990
1021
if (vRandom.size () != (size_t )(nTried + nNew))
991
1022
return -7 ;
@@ -1000,12 +1031,14 @@ int AddrManImpl::CheckAddrman() const
1000
1031
if (info.nRefCount )
1001
1032
return -2 ;
1002
1033
setTried.insert (n);
1034
+ local_counts[info.GetNetwork ()].n_tried ++;
1003
1035
} else {
1004
1036
if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
1005
1037
return -3 ;
1006
1038
if (!info.nRefCount )
1007
1039
return -4 ;
1008
1040
mapNew[n] = info.nRefCount ;
1041
+ local_counts[info.GetNetwork ()].n_new ++;
1009
1042
}
1010
1043
const auto it{mapAddr.find (info)};
1011
1044
if (it == mapAddr.end () || it->second != n) {
@@ -1065,6 +1098,17 @@ int AddrManImpl::CheckAddrman() const
1065
1098
if (nKey.IsNull ())
1066
1099
return -16 ;
1067
1100
1101
+ // It's possible that m_network_counts may have all-zero entries that local_counts
1102
+ // doesn't have if addrs from a network were being added and then removed again in the past.
1103
+ if (m_network_counts.size () < local_counts.size ()) {
1104
+ return -20 ;
1105
+ }
1106
+ for (const auto & [net, count] : m_network_counts) {
1107
+ if (local_counts[net].n_new != count.n_new || local_counts[net].n_tried != count.n_tried ) {
1108
+ return -21 ;
1109
+ }
1110
+ }
1111
+
1068
1112
return 0 ;
1069
1113
}
1070
1114
@@ -1074,6 +1118,15 @@ size_t AddrManImpl::size() const
1074
1118
return vRandom.size ();
1075
1119
}
1076
1120
1121
+ size_t AddrManImpl::Size (std::optional<Network> net, std::optional<bool > in_new) const
1122
+ {
1123
+ LOCK (cs);
1124
+ Check ();
1125
+ auto ret = Size_ (net, in_new);
1126
+ Check ();
1127
+ return ret;
1128
+ }
1129
+
1077
1130
bool AddrManImpl::Add (const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
1078
1131
{
1079
1132
LOCK (cs);
@@ -1191,6 +1244,11 @@ size_t AddrMan::size() const
1191
1244
return m_impl->size ();
1192
1245
}
1193
1246
1247
+ size_t AddrMan::Size (std::optional<Network> net, std::optional<bool > in_new) const
1248
+ {
1249
+ return m_impl->Size (net, in_new);
1250
+ }
1251
+
1194
1252
bool AddrMan::Add (const std::vector<CAddress>& vAddr, const CNetAddr& source, std::chrono::seconds time_penalty)
1195
1253
{
1196
1254
return m_impl->Add (vAddr, source, time_penalty);
0 commit comments