Skip to content

Commit 1943156

Browse files
committed
[net] Move asmap into NetGroupManager
1 parent 17c24d4 commit 1943156

16 files changed

+158
-132
lines changed

Diff for: src/addrdb.cpp

+5-4
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) {

Diff for: src/addrdb.h

+2-1
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)

Diff for: src/addrman.cpp

+22-32
Original file line numberDiff line numberDiff line change
@@ -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) {
@@ -219,8 +219,8 @@ void AddrManImpl::Serialize(Stream& s_) const
219219
// Store asmap checksum after bucket entries so that it
220220
// can be ignored by older clients for backward compatibility.
221221
uint256 asmap_checksum;
222-
if (m_asmap.size() != 0) {
223-
asmap_checksum = SerializeHash(m_asmap);
222+
if (m_netgroupman.GetAsmap().size() != 0) {
223+
asmap_checksum = SerializeHash(m_netgroupman.GetAsmap());
224224
}
225225
s << asmap_checksum;
226226
}
@@ -298,7 +298,7 @@ void AddrManImpl::Unserialize(Stream& s_)
298298
for (int n = 0; n < nTried; n++) {
299299
AddrInfo info;
300300
s >> info;
301-
int nKBucket = info.GetTriedBucket(nKey, m_asmap);
301+
int nKBucket = info.GetTriedBucket(nKey, m_netgroupman.GetAsmap());
302302
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
303303
if (info.IsValid()
304304
&& vvTried[nKBucket][nKBucketPos] == -1) {
@@ -336,8 +336,8 @@ void AddrManImpl::Unserialize(Stream& s_)
336336
// to restore the entries to the buckets/positions they were in before
337337
// serialization.
338338
uint256 supplied_asmap_checksum;
339-
if (m_asmap.size() != 0) {
340-
supplied_asmap_checksum = SerializeHash(m_asmap);
339+
if (m_netgroupman.GetAsmap().size() != 0) {
340+
supplied_asmap_checksum = SerializeHash(m_netgroupman.GetAsmap());
341341
}
342342
uint256 serialized_asmap_checksum;
343343
if (format >= Format::V2_ASMAP) {
@@ -371,7 +371,7 @@ void AddrManImpl::Unserialize(Stream& s_)
371371
} else {
372372
// In case the new table data cannot be used (bucket count wrong or new asmap),
373373
// try to give them a reference based on their primary source address.
374-
bucket = info.GetNewBucket(nKey, m_asmap);
374+
bucket = info.GetNewBucket(nKey, m_netgroupman.GetAsmap());
375375
bucket_position = info.GetBucketPosition(nKey, true, bucket);
376376
if (vvNew[bucket][bucket_position] == -1) {
377377
vvNew[bucket][bucket_position] = entry_index;
@@ -495,7 +495,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
495495
AssertLockHeld(cs);
496496

497497
// remove the entry from all new buckets
498-
const int start_bucket{info.GetNewBucket(nKey, m_asmap)};
498+
const int start_bucket{info.GetNewBucket(nKey, m_netgroupman.GetAsmap())};
499499
for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; ++n) {
500500
const int bucket{(start_bucket + n) % ADDRMAN_NEW_BUCKET_COUNT};
501501
const int pos{info.GetBucketPosition(nKey, true, bucket)};
@@ -510,7 +510,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
510510
assert(info.nRefCount == 0);
511511

512512
// which tried bucket to move the entry to
513-
int nKBucket = info.GetTriedBucket(nKey, m_asmap);
513+
int nKBucket = info.GetTriedBucket(nKey, m_netgroupman.GetAsmap());
514514
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
515515

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

528528
// find which new bucket it belongs to
529-
int nUBucket = infoOld.GetNewBucket(nKey, m_asmap);
529+
int nUBucket = infoOld.GetNewBucket(nKey, m_netgroupman.GetAsmap());
530530
int nUBucketPos = infoOld.GetBucketPosition(nKey, true, nUBucket);
531531
ClearNew(nUBucket, nUBucketPos);
532532
assert(vvNew[nUBucket][nUBucketPos] == -1);
@@ -594,7 +594,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
594594
nNew++;
595595
}
596596

597-
int nUBucket = pinfo->GetNewBucket(nKey, source, m_asmap);
597+
int nUBucket = pinfo->GetNewBucket(nKey, source, m_netgroupman.GetAsmap());
598598
int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket);
599599
bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
600600
if (vvNew[nUBucket][nUBucketPos] != nId) {
@@ -610,7 +610,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
610610
pinfo->nRefCount++;
611611
vvNew[nUBucket][nUBucketPos] = nId;
612612
LogPrint(BCLog::ADDRMAN, "Added %s mapped to AS%i to new[%i][%i]\n",
613-
addr.ToString(), addr.GetMappedAS(m_asmap), nUBucket, nUBucketPos);
613+
addr.ToString(), addr.GetMappedAS(m_netgroupman.GetAsmap()), nUBucket, nUBucketPos);
614614
} else {
615615
if (pinfo->nRefCount == 0) {
616616
Delete(nId);
@@ -650,7 +650,7 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
650650

651651

652652
// which tried bucket to move the entry to
653-
int tried_bucket = info.GetTriedBucket(nKey, m_asmap);
653+
int tried_bucket = info.GetTriedBucket(nKey, m_netgroupman.GetAsmap());
654654
int tried_bucket_pos = info.GetBucketPosition(nKey, false, tried_bucket);
655655

656656
// Will moving this address into tried evict another entry?
@@ -669,7 +669,7 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
669669
// move nId to the tried tables
670670
MakeTried(info, nId);
671671
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);
672+
addr.ToString(), addr.GetMappedAS(m_netgroupman.GetAsmap()), tried_bucket, tried_bucket_pos);
673673
return true;
674674
}
675675
}
@@ -863,7 +863,7 @@ void AddrManImpl::ResolveCollisions_()
863863
AddrInfo& info_new = mapInfo[id_new];
864864

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

931931
// which tried bucket to move the entry to
932-
int tried_bucket = newInfo.GetTriedBucket(nKey, m_asmap);
932+
int tried_bucket = newInfo.GetTriedBucket(nKey, m_netgroupman.GetAsmap());
933933
int tried_bucket_pos = newInfo.GetBucketPosition(nKey, false, tried_bucket);
934934

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

947947
if(addr_info->fInTried) {
948-
int bucket{addr_info->GetTriedBucket(nKey, m_asmap)};
948+
int bucket{addr_info->GetTriedBucket(nKey, m_netgroupman.GetAsmap())};
949949
return AddressPosition(/*tried_in=*/true,
950950
/*multiplicity_in=*/1,
951951
/*bucket_in=*/bucket,
952952
/*position_in=*/addr_info->GetBucketPosition(nKey, false, bucket));
953953
} else {
954-
int bucket{addr_info->GetNewBucket(nKey, m_asmap)};
954+
int bucket{addr_info->GetNewBucket(nKey, m_netgroupman.GetAsmap())};
955955
return AddressPosition(/*tried_in=*/false,
956956
/*multiplicity_in=*/addr_info->nRefCount,
957957
/*bucket_in=*/bucket,
@@ -1026,7 +1026,7 @@ int AddrManImpl::CheckAddrman() const
10261026
if (!setTried.count(vvTried[n][i]))
10271027
return -11;
10281028
const auto it{mapInfo.find(vvTried[n][i])};
1029-
if (it == mapInfo.end() || it->second.GetTriedBucket(nKey, m_asmap) != n) {
1029+
if (it == mapInfo.end() || it->second.GetTriedBucket(nKey, m_netgroupman.GetAsmap()) != n) {
10301030
return -17;
10311031
}
10321032
if (it->second.GetBucketPosition(nKey, false, n) != i) {
@@ -1154,13 +1154,8 @@ std::optional<AddressPosition> AddrManImpl::FindAddressEntry(const CAddress& add
11541154
return entry;
11551155
}
11561156

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)) {}
1157+
AddrMan::AddrMan(const NetGroupManager& netgroupman, bool deterministic, int32_t consistency_check_ratio)
1158+
: m_impl(std::make_unique<AddrManImpl>(netgroupman, deterministic, consistency_check_ratio)) {}
11641159

11651160
AddrMan::~AddrMan() = default;
11661161

@@ -1235,11 +1230,6 @@ void AddrMan::SetServices(const CService& addr, ServiceFlags nServices)
12351230
m_impl->SetServices(addr, nServices);
12361231
}
12371232

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

Diff for: src/addrman.h

+2-3
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.

Diff for: src/addrman_impl.h

+3-18
Original file line numberDiff line numberDiff line change
@@ -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);

Diff for: src/bench/addrman.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include <addrman.h>
66
#include <bench/bench.h>
7+
#include <netgroup.h>
78
#include <random.h>
89
#include <util/check.h>
910
#include <util/time.h>
@@ -16,7 +17,7 @@
1617
static constexpr size_t NUM_SOURCES = 64;
1718
static constexpr size_t NUM_ADDRESSES_PER_SOURCE = 256;
1819

19-
static const std::vector<bool> EMPTY_ASMAP;
20+
static NetGroupManager EMPTY_NETGROUPMAN{std::vector<bool>()};
2021
static constexpr uint32_t ADDRMAN_CONSISTENCY_CHECK_RATIO{0};
2122

2223
static std::vector<CAddress> g_sources;
@@ -77,14 +78,14 @@ static void AddrManAdd(benchmark::Bench& bench)
7778
CreateAddresses();
7879

7980
bench.run([&] {
80-
AddrMan addrman{EMPTY_ASMAP, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
81+
AddrMan addrman{EMPTY_NETGROUPMAN, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
8182
AddAddressesToAddrMan(addrman);
8283
});
8384
}
8485

8586
static void AddrManSelect(benchmark::Bench& bench)
8687
{
87-
AddrMan addrman{EMPTY_ASMAP, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
88+
AddrMan addrman{EMPTY_NETGROUPMAN, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
8889

8990
FillAddrMan(addrman);
9091

@@ -96,7 +97,7 @@ static void AddrManSelect(benchmark::Bench& bench)
9697

9798
static void AddrManGetAddr(benchmark::Bench& bench)
9899
{
99-
AddrMan addrman{EMPTY_ASMAP, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
100+
AddrMan addrman{EMPTY_NETGROUPMAN, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
100101

101102
FillAddrMan(addrman);
102103

@@ -125,7 +126,7 @@ static void AddrManAddThenGood(benchmark::Bench& bench)
125126
//
126127
// This has some overhead (exactly the result of AddrManAdd benchmark), but that overhead is constant so improvements in
127128
// AddrMan::Good() will still be noticeable.
128-
AddrMan addrman{EMPTY_ASMAP, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
129+
AddrMan addrman{EMPTY_NETGROUPMAN, /*deterministic=*/false, ADDRMAN_CONSISTENCY_CHECK_RATIO};
129130
AddAddressesToAddrMan(addrman);
130131

131132
markSomeAsGood(addrman);

Diff for: src/init.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -1256,20 +1256,22 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
12561256

12571257
// Initialize netgroup manager
12581258
assert(!node.netgroupman);
1259-
node.netgroupman = std::make_unique<NetGroupManager>();
1259+
node.netgroupman = std::make_unique<NetGroupManager>(std::move(asmap));
12601260

12611261
// Initialize addrman
12621262
assert(!node.addrman);
12631263
uiInterface.InitMessage(_("Loading P2P addresses…").translated);
1264-
if (const auto error{LoadAddrman(asmap, args, node.addrman)}) {
1264+
if (const auto error{LoadAddrman(*node.netgroupman, args, node.addrman)}) {
12651265
return InitError(*error);
12661266
}
12671267
}
12681268

12691269
assert(!node.banman);
12701270
node.banman = std::make_unique<BanMan>(gArgs.GetDataDirNet() / "banlist", &uiInterface, args.GetIntArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
12711271
assert(!node.connman);
1272-
node.connman = std::make_unique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()), GetRand(std::numeric_limits<uint64_t>::max()), *node.addrman, args.GetBoolArg("-networkactive", true));
1272+
node.connman = std::make_unique<CConnman>(GetRand(std::numeric_limits<uint64_t>::max()),
1273+
GetRand(std::numeric_limits<uint64_t>::max()),
1274+
*node.addrman, *node.netgroupman, args.GetBoolArg("-networkactive", true));
12731275

12741276
assert(!node.fee_estimator);
12751277
// Don't initialize fee estimation with old data if we don't relay transactions,

0 commit comments

Comments
 (0)