Skip to content

Commit 505ba39

Browse files
committed
Merge bitcoin/bitcoin#22910: net: Encapsulate asmap in NetGroupManager
36f814c [netgroupman] Remove NetGroupManager::GetAsmap() (John Newbery) 4709fc2 [netgroupman] Move asmap checksum calculation to NetGroupManager (John Newbery) 1b978a7 [netgroupman] Move GetMappedAS() and GetGroup() logic to NetGroupManager (John Newbery) ddb4101 [net] Only use public CNetAddr functions and data in GetMappedAS() and GetGroup() (John Newbery) 6b22681 [netgroupman] Add GetMappedAS() and GetGroup() (John Newbery) 1943156 [net] Move asmap into NetGroupManager (John Newbery) 17c24d4 [init] Add netgroupman to node.context (John Newbery) 9b38367 [build] Add netgroup.cpp|h (John Newbery) Pull request description: The asmap data is currently owned by addrman, but is used by both addrman and connman. #22791 made the data const and private (so that it can't be updated by other components), but it is still passed out of addrman as a reference to const, and used by `CNetAddress` to calculate the group and AS of the net address. This RFC PR proposes to move all asmap data and logic into a new `NetGroupManager` component. This is initialized at startup, and the client components addrman and connman simply call `NetGroupManager::GetGroup(const CAddress&)` and `NetGroupManager::GetMappedAS(const CAddress&)` to get the net group and AS of an address. ACKs for top commit: mzumsande: Code Review ACK 36f814c jnewbery: CI failure seems spurious. I rebased onto latest master to trigger a new CI run, but whilst I was doing that, mzumsande ACKed bitcoin/bitcoin@36f814c, so I've reverted to that. dergoegge: Code review ACK 36f814c Tree-SHA512: 244a89cdfd720d8cce679eae5b7951e1b46b37835fccb6bdfa362856761bb110e79e263a6eeee8246140890f3bee2850e9baa7bc14a388a588e0e29b9d275175
2 parents 7a4ac71 + 36f814c commit 505ba39

24 files changed

+370
-302
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ BITCOIN_CORE_H = \
180180
net_types.h \
181181
netaddress.h \
182182
netbase.h \
183+
netgroup.h \
183184
netmessagemaker.h \
184185
node/blockstorage.h \
185186
node/caches.h \
@@ -352,6 +353,7 @@ libbitcoin_node_a_SOURCES = \
352353
init.cpp \
353354
mapport.cpp \
354355
net.cpp \
356+
netgroup.cpp \
355357
net_processing.cpp \
356358
node/blockstorage.cpp \
357359
node/caches.cpp \

src/addrdb.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <hash.h>
1414
#include <logging/timer.h>
1515
#include <netbase.h>
16+
#include <netgroup.h>
1617
#include <random.h>
1718
#include <streams.h>
1819
#include <tinyformat.h>
@@ -182,10 +183,10 @@ void ReadFromStream(AddrMan& addr, CDataStream& ssPeers)
182183
DeserializeDB(ssPeers, addr, false);
183184
}
184185

185-
std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const ArgsManager& args, std::unique_ptr<AddrMan>& addrman)
186+
std::optional<bilingual_str> LoadAddrman(const NetGroupManager& netgroupman, const ArgsManager& args, std::unique_ptr<AddrMan>& addrman)
186187
{
187188
auto check_addrman = std::clamp<int32_t>(args.GetIntArg("-checkaddrman", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, 1000000);
188-
addrman = std::make_unique<AddrMan>(asmap, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);
189+
addrman = std::make_unique<AddrMan>(netgroupman, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);
189190

190191
int64_t nStart = GetTimeMillis();
191192
const auto path_addr{args.GetDataDirNet() / "peers.dat"};
@@ -194,7 +195,7 @@ std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const A
194195
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), GetTimeMillis() - nStart);
195196
} catch (const DbNotFoundError&) {
196197
// Addrman can be in an inconsistent state after failure, reset it
197-
addrman = std::make_unique<AddrMan>(asmap, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);
198+
addrman = std::make_unique<AddrMan>(netgroupman, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);
198199
LogPrintf("Creating peers.dat because the file was not found (%s)\n", fs::quoted(fs::PathToString(path_addr)));
199200
DumpPeerAddresses(args, *addrman);
200201
} catch (const InvalidAddrManVersionError&) {
@@ -203,7 +204,7 @@ std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const A
203204
return strprintf(_("Failed to rename invalid peers.dat file. Please move or delete it and try again."));
204205
}
205206
// Addrman can be in an inconsistent state after failure, reset it
206-
addrman = std::make_unique<AddrMan>(asmap, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);
207+
addrman = std::make_unique<AddrMan>(netgroupman, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);
207208
LogPrintf("Creating new peers.dat because the file version was not compatible (%s). Original backed up to peers.dat.bak\n", fs::quoted(fs::PathToString(path_addr)));
208209
DumpPeerAddresses(args, *addrman);
209210
} catch (const std::exception& e) {

src/addrdb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class ArgsManager;
1717
class AddrMan;
1818
class CAddress;
1919
class CDataStream;
20+
class NetGroupManager;
2021
struct bilingual_str;
2122

2223
bool DumpPeerAddresses(const ArgsManager& args, const AddrMan& addr);
@@ -48,7 +49,7 @@ class CBanDB
4849
};
4950

5051
/** Returns an error string on failure */
51-
std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const ArgsManager& args, std::unique_ptr<AddrMan>& addrman);
52+
std::optional<bilingual_str> LoadAddrman(const NetGroupManager& netgroupman, const ArgsManager& args, std::unique_ptr<AddrMan>& addrman);
5253

5354
/**
5455
* Dump the anchor IP address database (anchors.dat)

src/addrman.cpp

Lines changed: 25 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,17 @@ static constexpr size_t ADDRMAN_SET_TRIED_COLLISION_SIZE{10};
4343
/** The maximum time we'll spend trying to resolve a tried table collision, in seconds */
4444
static constexpr int64_t ADDRMAN_TEST_WINDOW{40*60}; // 40 minutes
4545

46-
int AddrInfo::GetTriedBucket(const uint256& nKey, const std::vector<bool>& asmap) const
46+
int AddrInfo::GetTriedBucket(const uint256& nKey, const NetGroupManager& netgroupman) const
4747
{
4848
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetCheapHash();
49-
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup(asmap) << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetCheapHash();
49+
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << netgroupman.GetGroup(*this) << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetCheapHash();
5050
return hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
5151
}
5252

53-
int AddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src, const std::vector<bool>& asmap) const
53+
int AddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src, const NetGroupManager& netgroupman) const
5454
{
55-
std::vector<unsigned char> vchSourceGroupKey = src.GetGroup(asmap);
56-
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup(asmap) << vchSourceGroupKey).GetCheapHash();
55+
std::vector<unsigned char> vchSourceGroupKey = netgroupman.GetGroup(src);
56+
uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << netgroupman.GetGroup(*this) << vchSourceGroupKey).GetCheapHash();
5757
uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetCheapHash();
5858
return hash2 % ADDRMAN_NEW_BUCKET_COUNT;
5959
}
@@ -99,11 +99,11 @@ double AddrInfo::GetChance(int64_t nNow) const
9999
return fChance;
100100
}
101101

102-
AddrManImpl::AddrManImpl(std::vector<bool>&& asmap, bool deterministic, int32_t consistency_check_ratio)
102+
AddrManImpl::AddrManImpl(const NetGroupManager& netgroupman, bool deterministic, int32_t consistency_check_ratio)
103103
: insecure_rand{deterministic}
104104
, nKey{deterministic ? uint256{1} : insecure_rand.rand256()}
105105
, m_consistency_check_ratio{consistency_check_ratio}
106-
, m_asmap{std::move(asmap)}
106+
, m_netgroupman{netgroupman}
107107
{
108108
for (auto& bucket : vvNew) {
109109
for (auto& entry : bucket) {
@@ -218,11 +218,7 @@ void AddrManImpl::Serialize(Stream& s_) const
218218
}
219219
// Store asmap checksum after bucket entries so that it
220220
// can be ignored by older clients for backward compatibility.
221-
uint256 asmap_checksum;
222-
if (m_asmap.size() != 0) {
223-
asmap_checksum = SerializeHash(m_asmap);
224-
}
225-
s << asmap_checksum;
221+
s << m_netgroupman.GetAsmapChecksum();
226222
}
227223

228224
template <typename Stream>
@@ -298,7 +294,7 @@ void AddrManImpl::Unserialize(Stream& s_)
298294
for (int n = 0; n < nTried; n++) {
299295
AddrInfo info;
300296
s >> info;
301-
int nKBucket = info.GetTriedBucket(nKey, m_asmap);
297+
int nKBucket = info.GetTriedBucket(nKey, m_netgroupman);
302298
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
303299
if (info.IsValid()
304300
&& vvTried[nKBucket][nKBucketPos] == -1) {
@@ -335,10 +331,7 @@ void AddrManImpl::Unserialize(Stream& s_)
335331
// If the bucket count and asmap checksum haven't changed, then attempt
336332
// to restore the entries to the buckets/positions they were in before
337333
// serialization.
338-
uint256 supplied_asmap_checksum;
339-
if (m_asmap.size() != 0) {
340-
supplied_asmap_checksum = SerializeHash(m_asmap);
341-
}
334+
uint256 supplied_asmap_checksum{m_netgroupman.GetAsmapChecksum()};
342335
uint256 serialized_asmap_checksum;
343336
if (format >= Format::V2_ASMAP) {
344337
s >> serialized_asmap_checksum;
@@ -371,7 +364,7 @@ void AddrManImpl::Unserialize(Stream& s_)
371364
} else {
372365
// In case the new table data cannot be used (bucket count wrong or new asmap),
373366
// try to give them a reference based on their primary source address.
374-
bucket = info.GetNewBucket(nKey, m_asmap);
367+
bucket = info.GetNewBucket(nKey, m_netgroupman);
375368
bucket_position = info.GetBucketPosition(nKey, true, bucket);
376369
if (vvNew[bucket][bucket_position] == -1) {
377370
vvNew[bucket][bucket_position] = entry_index;
@@ -495,7 +488,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
495488
AssertLockHeld(cs);
496489

497490
// remove the entry from all new buckets
498-
const int start_bucket{info.GetNewBucket(nKey, m_asmap)};
491+
const int start_bucket{info.GetNewBucket(nKey, m_netgroupman)};
499492
for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; ++n) {
500493
const int bucket{(start_bucket + n) % ADDRMAN_NEW_BUCKET_COUNT};
501494
const int pos{info.GetBucketPosition(nKey, true, bucket)};
@@ -510,7 +503,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
510503
assert(info.nRefCount == 0);
511504

512505
// which tried bucket to move the entry to
513-
int nKBucket = info.GetTriedBucket(nKey, m_asmap);
506+
int nKBucket = info.GetTriedBucket(nKey, m_netgroupman);
514507
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
515508

516509
// first make space to add it (the existing tried entry there is moved to new, deleting whatever is there).
@@ -526,7 +519,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
526519
nTried--;
527520

528521
// find which new bucket it belongs to
529-
int nUBucket = infoOld.GetNewBucket(nKey, m_asmap);
522+
int nUBucket = infoOld.GetNewBucket(nKey, m_netgroupman);
530523
int nUBucketPos = infoOld.GetBucketPosition(nKey, true, nUBucket);
531524
ClearNew(nUBucket, nUBucketPos);
532525
assert(vvNew[nUBucket][nUBucketPos] == -1);
@@ -594,7 +587,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
594587
nNew++;
595588
}
596589

597-
int nUBucket = pinfo->GetNewBucket(nKey, source, m_asmap);
590+
int nUBucket = pinfo->GetNewBucket(nKey, source, m_netgroupman);
598591
int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket);
599592
bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
600593
if (vvNew[nUBucket][nUBucketPos] != nId) {
@@ -610,7 +603,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
610603
pinfo->nRefCount++;
611604
vvNew[nUBucket][nUBucketPos] = nId;
612605
LogPrint(BCLog::ADDRMAN, "Added %s mapped to AS%i to new[%i][%i]\n",
613-
addr.ToString(), addr.GetMappedAS(m_asmap), nUBucket, nUBucketPos);
606+
addr.ToString(), m_netgroupman.GetMappedAS(addr), nUBucket, nUBucketPos);
614607
} else {
615608
if (pinfo->nRefCount == 0) {
616609
Delete(nId);
@@ -650,7 +643,7 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
650643

651644

652645
// which tried bucket to move the entry to
653-
int tried_bucket = info.GetTriedBucket(nKey, m_asmap);
646+
int tried_bucket = info.GetTriedBucket(nKey, m_netgroupman);
654647
int tried_bucket_pos = info.GetBucketPosition(nKey, false, tried_bucket);
655648

656649
// Will moving this address into tried evict another entry?
@@ -669,7 +662,7 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
669662
// move nId to the tried tables
670663
MakeTried(info, nId);
671664
LogPrint(BCLog::ADDRMAN, "Moved %s mapped to AS%i to tried[%i][%i]\n",
672-
addr.ToString(), addr.GetMappedAS(m_asmap), tried_bucket, tried_bucket_pos);
665+
addr.ToString(), m_netgroupman.GetMappedAS(addr), tried_bucket, tried_bucket_pos);
673666
return true;
674667
}
675668
}
@@ -863,7 +856,7 @@ void AddrManImpl::ResolveCollisions_()
863856
AddrInfo& info_new = mapInfo[id_new];
864857

865858
// Which tried bucket to move the entry to.
866-
int tried_bucket = info_new.GetTriedBucket(nKey, m_asmap);
859+
int tried_bucket = info_new.GetTriedBucket(nKey, m_netgroupman);
867860
int tried_bucket_pos = info_new.GetBucketPosition(nKey, false, tried_bucket);
868861
if (!info_new.IsValid()) { // id_new may no longer map to a valid address
869862
erase_collision = true;
@@ -929,7 +922,7 @@ std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision_()
929922
const AddrInfo& newInfo = mapInfo[id_new];
930923

931924
// which tried bucket to move the entry to
932-
int tried_bucket = newInfo.GetTriedBucket(nKey, m_asmap);
925+
int tried_bucket = newInfo.GetTriedBucket(nKey, m_netgroupman);
933926
int tried_bucket_pos = newInfo.GetBucketPosition(nKey, false, tried_bucket);
934927

935928
const AddrInfo& info_old = mapInfo[vvTried[tried_bucket][tried_bucket_pos]];
@@ -945,13 +938,13 @@ std::optional<AddressPosition> AddrManImpl::FindAddressEntry_(const CAddress& ad
945938
if (!addr_info) return std::nullopt;
946939

947940
if(addr_info->fInTried) {
948-
int bucket{addr_info->GetTriedBucket(nKey, m_asmap)};
941+
int bucket{addr_info->GetTriedBucket(nKey, m_netgroupman)};
949942
return AddressPosition(/*tried_in=*/true,
950943
/*multiplicity_in=*/1,
951944
/*bucket_in=*/bucket,
952945
/*position_in=*/addr_info->GetBucketPosition(nKey, false, bucket));
953946
} else {
954-
int bucket{addr_info->GetNewBucket(nKey, m_asmap)};
947+
int bucket{addr_info->GetNewBucket(nKey, m_netgroupman)};
955948
return AddressPosition(/*tried_in=*/false,
956949
/*multiplicity_in=*/addr_info->nRefCount,
957950
/*bucket_in=*/bucket,
@@ -1026,7 +1019,7 @@ int AddrManImpl::CheckAddrman() const
10261019
if (!setTried.count(vvTried[n][i]))
10271020
return -11;
10281021
const auto it{mapInfo.find(vvTried[n][i])};
1029-
if (it == mapInfo.end() || it->second.GetTriedBucket(nKey, m_asmap) != n) {
1022+
if (it == mapInfo.end() || it->second.GetTriedBucket(nKey, m_netgroupman) != n) {
10301023
return -17;
10311024
}
10321025
if (it->second.GetBucketPosition(nKey, false, n) != i) {
@@ -1154,13 +1147,8 @@ std::optional<AddressPosition> AddrManImpl::FindAddressEntry(const CAddress& add
11541147
return entry;
11551148
}
11561149

1157-
const std::vector<bool>& AddrManImpl::GetAsmap() const
1158-
{
1159-
return m_asmap;
1160-
}
1161-
1162-
AddrMan::AddrMan(std::vector<bool> asmap, bool deterministic, int32_t consistency_check_ratio)
1163-
: m_impl(std::make_unique<AddrManImpl>(std::move(asmap), deterministic, consistency_check_ratio)) {}
1150+
AddrMan::AddrMan(const NetGroupManager& netgroupman, bool deterministic, int32_t consistency_check_ratio)
1151+
: m_impl(std::make_unique<AddrManImpl>(netgroupman, deterministic, consistency_check_ratio)) {}
11641152

11651153
AddrMan::~AddrMan() = default;
11661154

@@ -1235,11 +1223,6 @@ void AddrMan::SetServices(const CService& addr, ServiceFlags nServices)
12351223
m_impl->SetServices(addr, nServices);
12361224
}
12371225

1238-
const std::vector<bool>& AddrMan::GetAsmap() const
1239-
{
1240-
return m_impl->GetAsmap();
1241-
}
1242-
12431226
std::optional<AddressPosition> AddrMan::FindAddressEntry(const CAddress& addr)
12441227
{
12451228
return m_impl->FindAddressEntry(addr);

src/addrman.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#define BITCOIN_ADDRMAN_H
88

99
#include <netaddress.h>
10+
#include <netgroup.h>
1011
#include <protocol.h>
1112
#include <streams.h>
1213
#include <timedata.h>
@@ -88,7 +89,7 @@ class AddrMan
8889
const std::unique_ptr<AddrManImpl> m_impl;
8990

9091
public:
91-
explicit AddrMan(std::vector<bool> asmap, bool deterministic, int32_t consistency_check_ratio);
92+
explicit AddrMan(const NetGroupManager& netgroupman, bool deterministic, int32_t consistency_check_ratio);
9293

9394
~AddrMan();
9495

@@ -172,8 +173,6 @@ class AddrMan
172173
//! Update an entry's service bits.
173174
void SetServices(const CService& addr, ServiceFlags nServices);
174175

175-
const std::vector<bool>& GetAsmap() const;
176-
177176
/** Test-only function
178177
* Find the address record in AddrMan and return information about its
179178
* position.

src/addrman_impl.h

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -76,15 +76,15 @@ class AddrInfo : public CAddress
7676
}
7777

7878
//! Calculate in which "tried" bucket this entry belongs
79-
int GetTriedBucket(const uint256 &nKey, const std::vector<bool> &asmap) const;
79+
int GetTriedBucket(const uint256& nKey, const NetGroupManager& netgroupman) const;
8080

8181
//! Calculate in which "new" bucket this entry belongs, given a certain source
82-
int GetNewBucket(const uint256 &nKey, const CNetAddr& src, const std::vector<bool> &asmap) const;
82+
int GetNewBucket(const uint256& nKey, const CNetAddr& src, const NetGroupManager& netgroupman) const;
8383

8484
//! Calculate in which "new" bucket this entry belongs, using its default source
85-
int GetNewBucket(const uint256 &nKey, const std::vector<bool> &asmap) const
85+
int GetNewBucket(const uint256& nKey, const NetGroupManager& netgroupman) const
8686
{
87-
return GetNewBucket(nKey, source, asmap);
87+
return GetNewBucket(nKey, source, netgroupman);
8888
}
8989

9090
//! Calculate in which position of a bucket to store this entry.
@@ -100,7 +100,7 @@ class AddrInfo : public CAddress
100100
class AddrManImpl
101101
{
102102
public:
103-
AddrManImpl(std::vector<bool>&& asmap, bool deterministic, int32_t consistency_check_ratio);
103+
AddrManImpl(const NetGroupManager& netgroupman, bool deterministic, int32_t consistency_check_ratio);
104104

105105
~AddrManImpl();
106106

@@ -140,8 +140,6 @@ class AddrManImpl
140140
std::optional<AddressPosition> FindAddressEntry(const CAddress& addr)
141141
EXCLUSIVE_LOCKS_REQUIRED(!cs);
142142

143-
const std::vector<bool>& GetAsmap() const;
144-
145143
friend class AddrManDeterministic;
146144

147145
private:
@@ -212,21 +210,8 @@ class AddrManImpl
212210
/** Perform consistency checks every m_consistency_check_ratio operations (if non-zero). */
213211
const int32_t m_consistency_check_ratio;
214212

215-
// Compressed IP->ASN mapping, loaded from a file when a node starts.
216-
// Should be always empty if no file was provided.
217-
// This mapping is then used for bucketing nodes in Addrman.
218-
//
219-
// If asmap is provided, nodes will be bucketed by
220-
// AS they belong to, in order to make impossible for a node
221-
// to connect to several nodes hosted in a single AS.
222-
// This is done in response to Erebus attack, but also to generally
223-
// diversify the connections every node creates,
224-
// especially useful when a large fraction of nodes
225-
// operate under a couple of cloud providers.
226-
//
227-
// If a new asmap was provided, the existing records
228-
// would be re-bucketed accordingly.
229-
const std::vector<bool> m_asmap;
213+
/** Reference to the netgroup manager. netgroupman must be constructed before addrman and destructed after. */
214+
const NetGroupManager& m_netgroupman;
230215

231216
//! Find an entry.
232217
AddrInfo* Find(const CService& addr, int* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);

0 commit comments

Comments
 (0)