Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions src/addrman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ void AddrManImpl::Serialize(Stream& s_) const

int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
s << nUBuckets;
std::unordered_map<int, int> mapUnkIds;
std::unordered_map<nid_type, int> mapUnkIds;
int nIds = 0;
for (const auto& entry : mapInfo) {
mapUnkIds[entry.first] = nIds;
Expand Down Expand Up @@ -397,7 +397,7 @@ void AddrManImpl::Unserialize(Stream& s_)
}
}

AddrInfo* AddrManImpl::Find(const CService& addr, int* pnId)
AddrInfo* AddrManImpl::Find(const CService& addr, nid_type* pnId)
{
AssertLockHeld(cs);

Expand All @@ -412,11 +412,11 @@ AddrInfo* AddrManImpl::Find(const CService& addr, int* pnId)
return nullptr;
}

AddrInfo* AddrManImpl::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId)
AddrInfo* AddrManImpl::Create(const CAddress& addr, const CNetAddr& addrSource, nid_type* pnId)
{
AssertLockHeld(cs);

int nId = nIdCount++;
nid_type nId = nIdCount++;
mapInfo[nId] = AddrInfo(addr, addrSource);
mapAddr[addr] = nId;
mapInfo[nId].nRandomPos = vRandom.size();
Expand All @@ -435,8 +435,8 @@ void AddrManImpl::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) const

assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());

int nId1 = vRandom[nRndPos1];
int nId2 = vRandom[nRndPos2];
nid_type nId1 = vRandom[nRndPos1];
nid_type nId2 = vRandom[nRndPos2];

const auto it_1{mapInfo.find(nId1)};
const auto it_2{mapInfo.find(nId2)};
Expand All @@ -450,7 +450,7 @@ void AddrManImpl::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) const
vRandom[nRndPos2] = nId1;
}

void AddrManImpl::Delete(int nId)
void AddrManImpl::Delete(nid_type nId)
{
AssertLockHeld(cs);

Expand All @@ -472,7 +472,7 @@ void AddrManImpl::ClearNew(int nUBucket, int nUBucketPos)

// if there is an entry in the specified bucket, delete it.
if (vvNew[nUBucket][nUBucketPos] != -1) {
int nIdDelete = vvNew[nUBucket][nUBucketPos];
nid_type nIdDelete = vvNew[nUBucket][nUBucketPos];
AddrInfo& infoDelete = mapInfo[nIdDelete];
assert(infoDelete.nRefCount > 0);
infoDelete.nRefCount--;
Expand All @@ -484,7 +484,7 @@ void AddrManImpl::ClearNew(int nUBucket, int nUBucketPos)
}
}

void AddrManImpl::MakeTried(AddrInfo& info, int nId)
void AddrManImpl::MakeTried(AddrInfo& info, nid_type nId)
{
AssertLockHeld(cs);

Expand All @@ -510,7 +510,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
// first make space to add it (the existing tried entry there is moved to new, deleting whatever is there).
if (vvTried[nKBucket][nKBucketPos] != -1) {
// find an item to evict
int nIdEvict = vvTried[nKBucket][nKBucketPos];
nid_type nIdEvict = vvTried[nKBucket][nKBucketPos];
assert(mapInfo.count(nIdEvict) == 1);
AddrInfo& infoOld = mapInfo[nIdEvict];

Expand Down Expand Up @@ -546,7 +546,7 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
if (!addr.IsRoutable())
return false;

int nId;
nid_type nId;
AddrInfo* pinfo = Find(addr, &nId);

// Do not set a penalty for a source's self-announcement
Expand Down Expand Up @@ -618,7 +618,7 @@ bool AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nT
{
AssertLockHeld(cs);

int nId;
nid_type nId;

nLastGood = nTime;

Expand Down Expand Up @@ -845,8 +845,8 @@ void AddrManImpl::ResolveCollisions_()
{
AssertLockHeld(cs);

for (std::set<int>::iterator it = m_tried_collisions.begin(); it != m_tried_collisions.end();) {
int id_new = *it;
for (std::set<nid_type>::iterator it = m_tried_collisions.begin(); it != m_tried_collisions.end();) {
nid_type id_new = *it;

bool erase_collision = false;

Expand All @@ -864,7 +864,7 @@ void AddrManImpl::ResolveCollisions_()
} else if (vvTried[tried_bucket][tried_bucket_pos] != -1) { // The position in the tried bucket is not empty

// Get the to-be-evicted address that is being tested
int id_old = vvTried[tried_bucket][tried_bucket_pos];
nid_type id_old = vvTried[tried_bucket][tried_bucket_pos];
AddrInfo& info_old = mapInfo[id_old];

// Has successfully connected in last X hours
Expand Down Expand Up @@ -908,11 +908,11 @@ std::pair<CAddress, int64_t> AddrManImpl::SelectTriedCollision_()

if (m_tried_collisions.size() == 0) return {};

std::set<int>::iterator it = m_tried_collisions.begin();
std::set<nid_type>::iterator it = m_tried_collisions.begin();

// Selects a random element from m_tried_collisions
std::advance(it, insecure_rand.randrange(m_tried_collisions.size()));
int id_new = *it;
nid_type id_new = *it;

// If id_new not found in mapInfo remove it from m_tried_collisions
if (mapInfo.count(id_new) != 1) {
Expand Down Expand Up @@ -975,14 +975,14 @@ int AddrManImpl::CheckAddrman() const
LOG_TIME_MILLIS_WITH_CATEGORY_MSG_ONCE(
strprintf("new %i, tried %i, total %u", nNew, nTried, vRandom.size()), BCLog::ADDRMAN);

std::unordered_set<int> setTried;
std::unordered_map<int, int> mapNew;
std::unordered_set<nid_type> setTried;
std::unordered_map<nid_type, int> mapNew;

if (vRandom.size() != (size_t)(nTried + nNew))
return -7;

for (const auto& entry : mapInfo) {
int n = entry.first;
nid_type n = entry.first;
const AddrInfo& info = entry.second;
if (info.fInTried) {
if (!info.nLastSuccess)
Expand Down
29 changes: 18 additions & 11 deletions src/addrman_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ static constexpr int ADDRMAN_NEW_BUCKET_COUNT{1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2
static constexpr int32_t ADDRMAN_BUCKET_SIZE_LOG2{6};
static constexpr int ADDRMAN_BUCKET_SIZE{1 << ADDRMAN_BUCKET_SIZE_LOG2};

/**
* User-defined type for the internally used nIds
* This used to be int, making it feasible for attackers to cause an overflow,
* see https://bitcoincore.org/en/2024/07/31/disclose-addrman-int-overflow/
*/
using nid_type = int64_t;

/**
* Extended statistics about a CAddress
*/
Expand Down Expand Up @@ -178,36 +185,36 @@ class AddrManImpl
static constexpr uint8_t INCOMPATIBILITY_BASE = 32;

//! last used nId
int nIdCount GUARDED_BY(cs){0};
nid_type nIdCount GUARDED_BY(cs){0};

//! table with information about all nIds
std::unordered_map<int, AddrInfo> mapInfo GUARDED_BY(cs);
std::unordered_map<nid_type, AddrInfo> mapInfo GUARDED_BY(cs);

//! find an nId based on its network address and port.
std::unordered_map<CService, int, CServiceHash> mapAddr GUARDED_BY(cs);
std::unordered_map<CService, nid_type, CServiceHash> mapAddr GUARDED_BY(cs);

//! randomly-ordered vector of all nIds
//! This is mutable because it is unobservable outside the class, so any
//! changes to it (even in const methods) are also unobservable.
mutable std::vector<int> vRandom GUARDED_BY(cs);
mutable std::vector<nid_type> vRandom GUARDED_BY(cs);

// number of "tried" entries
int nTried GUARDED_BY(cs){0};

//! list of "tried" buckets
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
nid_type vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);

//! number of (unique) "new" entries
int nNew GUARDED_BY(cs){0};

//! list of "new" buckets
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
nid_type vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);

//! last time Good was called (memory only). Initially set to 1 so that "never" is strictly worse.
int64_t nLastGood GUARDED_BY(cs){1};

//! Holds addrs inserted into tried table that collide with existing entries. Test-before-evict discipline used to resolve these collisions.
std::set<int> m_tried_collisions;
std::set<nid_type> m_tried_collisions;

/** Perform consistency checks every m_consistency_check_ratio operations (if non-zero). */
const int32_t m_consistency_check_ratio;
Expand All @@ -229,22 +236,22 @@ class AddrManImpl
const std::vector<bool> m_asmap;

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

//! Create a new entry and add it to the internal data structures mapInfo, mapAddr and vRandom.
AddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
AddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, nid_type* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);

//! Swap two elements in vRandom.
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) const EXCLUSIVE_LOCKS_REQUIRED(cs);

//! Delete an entry. It must not be in tried, and have refcount 0.
void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
void Delete(nid_type nId) EXCLUSIVE_LOCKS_REQUIRED(cs);

//! Clear a position in a "new" table. This is the only place where entries are actually deleted.
void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs);

//! Move an entry from the "new" table(s) to the "tried" table
void MakeTried(AddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
void MakeTried(AddrInfo& info, nid_type nId) EXCLUSIVE_LOCKS_REQUIRED(cs);

/** Attempt to add a single address to addrman's new table.
* @see AddrMan::Add() for parameters. */
Expand Down
2 changes: 1 addition & 1 deletion src/test/fuzz/addrman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ class AddrManDeterministic : public AddrMan
return false;
}

auto IdsReferToSameAddress = [&](int id, int other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
auto IdsReferToSameAddress = [&](nid_type id, nid_type other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
if (id == -1 && other_id == -1) {
return true;
}
Expand Down