Skip to content

Commit 5cf28d5

Browse files
committed
Merge bitcoin/bitcoin#22496: addrman: Remove addrman hotfixes
65332b1 [addrman] Remove RemoveInvalid() (John Newbery) Pull request description: PRs #22179 and #22112 (EDIT: later reverted in #22497) added hotfix code to addrman to remove invalid addresses and mutate the ports of I2P entries after entering into addrman. Those hotfixes included at least two addrman data corruption bugs: - #22467 (Assertion `nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size()' failed) - #22470 (Changing I2P ports in addrman may wronly skip some entries from "new" buckets) Hotfixing addrman is inherently dangerous. There are many members that have implicit assumptions on each others' state, and mutating those directly can lead to violating addrman's internal invariants. Instead of trying to hotfix addrman, just don't insert any invalid addresses. For now, those are addresses which fail `CNetAddr::IsValid()`. ACKs for top commit: sipa: utACK 65332b1. I tried to reason through scenarios that could introduce inconsistencies with this code, but can't find any. fanquake: ACK 65332b1 - Skipping the addition of invalid addresses (this code was initially added for Tor addrs) rather than adding all the invalids then removing them all when finishing unserializing seems like an improvement. Especially if it can be achieved with less code. Tree-SHA512: 023113764cb475572f15da7bf9824b62b79e10a7e359af2eee59017df354348d2aeed88de0fd4ad7a9f89a0dad10827f99d70af6f1cb20abb0eca2714689c8d7
2 parents 71797be + 65332b1 commit 5cf28d5

File tree

2 files changed

+7
-40
lines changed

2 files changed

+7
-40
lines changed

src/addrman.cpp

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -77,38 +77,6 @@ double CAddrInfo::GetChance(int64_t nNow) const
7777
return fChance;
7878
}
7979

80-
void CAddrMan::RemoveInvalid()
81-
{
82-
for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; ++bucket) {
83-
for (size_t i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
84-
const auto id = vvNew[bucket][i];
85-
if (id != -1 && !mapInfo[id].IsValid()) {
86-
ClearNew(bucket, i);
87-
}
88-
}
89-
}
90-
91-
for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; ++bucket) {
92-
for (size_t i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
93-
const auto id = vvTried[bucket][i];
94-
if (id == -1) {
95-
continue;
96-
}
97-
const auto& addr_info = mapInfo[id];
98-
if (addr_info.IsValid()) {
99-
continue;
100-
}
101-
vvTried[bucket][i] = -1;
102-
--nTried;
103-
SwapRandom(addr_info.nRandomPos, vRandom.size() - 1);
104-
vRandom.pop_back();
105-
mapAddr.erase(addr_info);
106-
mapInfo.erase(id);
107-
m_tried_collisions.erase(id);
108-
}
109-
}
110-
}
111-
11280
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
11381
{
11482
AssertLockHeld(cs);

src/addrman.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -365,7 +365,8 @@ class CAddrMan
365365
s >> info;
366366
int nKBucket = info.GetTriedBucket(nKey, m_asmap);
367367
int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
368-
if (vvTried[nKBucket][nKBucketPos] == -1) {
368+
if (info.IsValid()
369+
&& vvTried[nKBucket][nKBucketPos] == -1) {
369370
info.nRandomPos = vRandom.size();
370371
info.fInTried = true;
371372
vRandom.push_back(nIdCount);
@@ -419,6 +420,9 @@ class CAddrMan
419420
const int entry_index{bucket_entry.second};
420421
CAddrInfo& info = mapInfo[entry_index];
421422

423+
// Don't store the entry in the new bucket if it's not a valid address for our addrman
424+
if (!info.IsValid()) continue;
425+
422426
// The entry shouldn't appear in more than
423427
// ADDRMAN_NEW_BUCKETS_PER_ADDRESS. If it has already, just skip
424428
// this bucket_entry.
@@ -441,7 +445,7 @@ class CAddrMan
441445
}
442446
}
443447

444-
// Prune new entries with refcount 0 (as a result of collisions).
448+
// Prune new entries with refcount 0 (as a result of collisions or invalid address).
445449
int nLostUnk = 0;
446450
for (auto it = mapInfo.cbegin(); it != mapInfo.cend(); ) {
447451
if (it->second.fInTried == false && it->second.nRefCount == 0) {
@@ -453,11 +457,9 @@ class CAddrMan
453457
}
454458
}
455459
if (nLost + nLostUnk > 0) {
456-
LogPrint(BCLog::ADDRMAN, "addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
460+
LogPrint(BCLog::ADDRMAN, "addrman lost %i new and %i tried addresses due to collisions or invalid addresses\n", nLostUnk, nLost);
457461
}
458462

459-
RemoveInvalid();
460-
461463
Check();
462464
}
463465

@@ -772,9 +774,6 @@ class CAddrMan
772774
//! Update an entry's service bits.
773775
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
774776

775-
//! Remove invalid addresses.
776-
void RemoveInvalid() EXCLUSIVE_LOCKS_REQUIRED(cs);
777-
778777
friend class CAddrManTest;
779778
};
780779

0 commit comments

Comments
 (0)