mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 10:43:19 -03:00
[addrman] Introduce CAddrMan::Impl to encapsulate addrman implementation.
Introduce the pimpl pattern for CAddrMan to separate the implementation details from the externally used object representation. This reduces compile-time dependencies and conceptually clarifies AddrMan's interface from the implementation specifics. Since the unit & fuzz tests currently rely on accessing CAddrMan internals, this commit introduces addrman_impl.h, which is exclusively imported by addrman.cpp and test files. Review hint: git diff --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space
This commit is contained in:
parent
f2e5f38f09
commit
8af5b54f97
6 changed files with 371 additions and 245 deletions
|
@ -117,6 +117,7 @@ endif
|
||||||
BITCOIN_CORE_H = \
|
BITCOIN_CORE_H = \
|
||||||
addrdb.h \
|
addrdb.h \
|
||||||
addrman.h \
|
addrman.h \
|
||||||
|
addrman_impl.h \
|
||||||
attributes.h \
|
attributes.h \
|
||||||
banman.h \
|
banman.h \
|
||||||
base58.h \
|
base58.h \
|
||||||
|
|
157
src/addrman.cpp
157
src/addrman.cpp
|
@ -4,6 +4,7 @@
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <addrman.h>
|
#include <addrman.h>
|
||||||
|
#include <addrman_impl.h>
|
||||||
|
|
||||||
#include <clientversion.h>
|
#include <clientversion.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
|
@ -101,7 +102,7 @@ double CAddrInfo::GetChance(int64_t nNow) const
|
||||||
return fChance;
|
return fChance;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrMan::CAddrMan(std::vector<bool> asmap, bool deterministic, int32_t consistency_check_ratio)
|
AddrManImpl::AddrManImpl(std::vector<bool>&& asmap, bool deterministic, int32_t consistency_check_ratio)
|
||||||
: insecure_rand{deterministic}
|
: insecure_rand{deterministic}
|
||||||
, nKey{deterministic ? uint256{1} : insecure_rand.rand256()}
|
, nKey{deterministic ? uint256{1} : insecure_rand.rand256()}
|
||||||
, m_consistency_check_ratio{consistency_check_ratio}
|
, m_consistency_check_ratio{consistency_check_ratio}
|
||||||
|
@ -119,13 +120,13 @@ CAddrMan::CAddrMan(std::vector<bool> asmap, bool deterministic, int32_t consiste
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrMan::~CAddrMan()
|
AddrManImpl::~AddrManImpl()
|
||||||
{
|
{
|
||||||
nKey.SetNull();
|
nKey.SetNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Stream>
|
template <typename Stream>
|
||||||
void CAddrMan::Serialize(Stream& s_) const
|
void AddrManImpl::Serialize(Stream& s_) const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
|
||||||
|
@ -228,7 +229,7 @@ void CAddrMan::Serialize(Stream& s_) const
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Stream>
|
template <typename Stream>
|
||||||
void CAddrMan::Unserialize(Stream& s_)
|
void AddrManImpl::Unserialize(Stream& s_)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
|
|
||||||
|
@ -399,16 +400,7 @@ void CAddrMan::Unserialize(Stream& s_)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// explicit instantiation
|
CAddrInfo* AddrManImpl::Find(const CNetAddr& addr, int* pnId)
|
||||||
template void CAddrMan::Serialize(CHashWriter& s) const;
|
|
||||||
template void CAddrMan::Serialize(CAutoFile& s) const;
|
|
||||||
template void CAddrMan::Serialize(CDataStream& s) const;
|
|
||||||
template void CAddrMan::Unserialize(CAutoFile& s);
|
|
||||||
template void CAddrMan::Unserialize(CHashVerifier<CAutoFile>& s);
|
|
||||||
template void CAddrMan::Unserialize(CDataStream& s);
|
|
||||||
template void CAddrMan::Unserialize(CHashVerifier<CDataStream>& s);
|
|
||||||
|
|
||||||
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
|
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -423,7 +415,7 @@ CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId)
|
CAddrInfo* AddrManImpl::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -437,7 +429,7 @@ CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, in
|
||||||
return &mapInfo[nId];
|
return &mapInfo[nId];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) const
|
void AddrManImpl::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) const
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -461,7 +453,7 @@ void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) const
|
||||||
vRandom[nRndPos2] = nId1;
|
vRandom[nRndPos2] = nId1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Delete(int nId)
|
void AddrManImpl::Delete(int nId)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -477,7 +469,7 @@ void CAddrMan::Delete(int nId)
|
||||||
nNew--;
|
nNew--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::ClearNew(int nUBucket, int nUBucketPos)
|
void AddrManImpl::ClearNew(int nUBucket, int nUBucketPos)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -494,7 +486,7 @@ void CAddrMan::ClearNew(int nUBucket, int nUBucketPos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::MakeTried(CAddrInfo& info, int nId)
|
void AddrManImpl::MakeTried(CAddrInfo& info, int nId)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -547,7 +539,7 @@ void CAddrMan::MakeTried(CAddrInfo& info, int nId)
|
||||||
info.fInTried = true;
|
info.fInTried = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Good_(const CService& addr, bool test_before_evict, int64_t nTime)
|
void AddrManImpl::Good_(const CService& addr, bool test_before_evict, int64_t nTime)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -603,7 +595,7 @@ void CAddrMan::Good_(const CService& addr, bool test_before_evict, int64_t nTime
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
|
bool AddrManImpl::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -678,7 +670,7 @@ bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimeP
|
||||||
return fNew;
|
return fNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime)
|
void AddrManImpl::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -702,7 +694,7 @@ void CAddrMan::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrInfo CAddrMan::Select_(bool newOnly) const
|
CAddrInfo AddrManImpl::Select_(bool newOnly) const
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -753,8 +745,7 @@ CAddrInfo CAddrMan::Select_(bool newOnly) const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddrManImpl::GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size_t max_pct, std::optional<Network> network) const
|
||||||
void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size_t max_pct, std::optional<Network> network) const
|
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -789,7 +780,7 @@ void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Connected_(const CService& addr, int64_t nTime)
|
void AddrManImpl::Connected_(const CService& addr, int64_t nTime)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -811,7 +802,7 @@ void CAddrMan::Connected_(const CService& addr, int64_t nTime)
|
||||||
info.nTime = nTime;
|
info.nTime = nTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::SetServices_(const CService& addr, ServiceFlags nServices)
|
void AddrManImpl::SetServices_(const CService& addr, ServiceFlags nServices)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -831,7 +822,7 @@ void CAddrMan::SetServices_(const CService& addr, ServiceFlags nServices)
|
||||||
info.nServices = nServices;
|
info.nServices = nServices;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::ResolveCollisions_()
|
void AddrManImpl::ResolveCollisions_()
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -892,7 +883,7 @@ void CAddrMan::ResolveCollisions_()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrInfo CAddrMan::SelectTriedCollision_()
|
CAddrInfo AddrManImpl::SelectTriedCollision_()
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -921,7 +912,7 @@ CAddrInfo CAddrMan::SelectTriedCollision_()
|
||||||
return mapInfo[id_old];
|
return mapInfo[id_old];
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Check() const
|
void AddrManImpl::Check() const
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -936,7 +927,7 @@ void CAddrMan::Check() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int CAddrMan::ForceCheckAddrman() const
|
int AddrManImpl::ForceCheckAddrman() const
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
||||||
|
@ -1024,13 +1015,13 @@ int CAddrMan::ForceCheckAddrman() const
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t CAddrMan::size() const
|
size_t AddrManImpl::size() const
|
||||||
{
|
{
|
||||||
LOCK(cs); // TODO: Cache this in an atomic to avoid this overhead
|
LOCK(cs); // TODO: Cache this in an atomic to avoid this overhead
|
||||||
return vRandom.size();
|
return vRandom.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CAddrMan::Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty)
|
bool AddrManImpl::Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
int nAdd = 0;
|
int nAdd = 0;
|
||||||
|
@ -1044,7 +1035,7 @@ bool CAddrMan::Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, i
|
||||||
return nAdd > 0;
|
return nAdd > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Good(const CService &addr, int64_t nTime)
|
void AddrManImpl::Good(const CService &addr, int64_t nTime)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
Check();
|
Check();
|
||||||
|
@ -1052,7 +1043,7 @@ void CAddrMan::Good(const CService &addr, int64_t nTime)
|
||||||
Check();
|
Check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Attempt(const CService &addr, bool fCountFailure, int64_t nTime)
|
void AddrManImpl::Attempt(const CService &addr, bool fCountFailure, int64_t nTime)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
Check();
|
Check();
|
||||||
|
@ -1060,8 +1051,7 @@ void CAddrMan::Attempt(const CService &addr, bool fCountFailure, int64_t nTime)
|
||||||
Check();
|
Check();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AddrManImpl::ResolveCollisions()
|
||||||
void CAddrMan::ResolveCollisions()
|
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
Check();
|
Check();
|
||||||
|
@ -1069,7 +1059,7 @@ void CAddrMan::ResolveCollisions()
|
||||||
Check();
|
Check();
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrInfo CAddrMan::SelectTriedCollision()
|
CAddrInfo AddrManImpl::SelectTriedCollision()
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
Check();
|
Check();
|
||||||
|
@ -1078,7 +1068,7 @@ CAddrInfo CAddrMan::SelectTriedCollision()
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrInfo CAddrMan::Select(bool newOnly) const
|
CAddrInfo AddrManImpl::Select(bool newOnly) const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
Check();
|
Check();
|
||||||
|
@ -1087,7 +1077,7 @@ CAddrInfo CAddrMan::Select(bool newOnly) const
|
||||||
return addrRet;
|
return addrRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CAddress> CAddrMan::GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
|
std::vector<CAddress> AddrManImpl::GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
Check();
|
Check();
|
||||||
|
@ -1097,7 +1087,7 @@ std::vector<CAddress> CAddrMan::GetAddr(size_t max_addresses, size_t max_pct, st
|
||||||
return vAddr;
|
return vAddr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::Connected(const CService &addr, int64_t nTime)
|
void AddrManImpl::Connected(const CService &addr, int64_t nTime)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
Check();
|
Check();
|
||||||
|
@ -1105,7 +1095,7 @@ void CAddrMan::Connected(const CService &addr, int64_t nTime)
|
||||||
Check();
|
Check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CAddrMan::SetServices(const CService &addr, ServiceFlags nServices)
|
void AddrManImpl::SetServices(const CService &addr, ServiceFlags nServices)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(cs);
|
||||||
Check();
|
Check();
|
||||||
|
@ -1113,7 +1103,88 @@ void CAddrMan::SetServices(const CService &addr, ServiceFlags nServices)
|
||||||
Check();
|
Check();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::vector<bool>& CAddrMan::GetAsmap() const
|
const std::vector<bool>& AddrManImpl::GetAsmap() const
|
||||||
{
|
{
|
||||||
return m_asmap;
|
return m_asmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CAddrMan::CAddrMan(std::vector<bool> asmap, bool deterministic, int32_t consistency_check_ratio)
|
||||||
|
: m_impl(std::make_unique<AddrManImpl>(std::move(asmap), deterministic, consistency_check_ratio)) {}
|
||||||
|
|
||||||
|
CAddrMan::~CAddrMan() = default;
|
||||||
|
|
||||||
|
template <typename Stream>
|
||||||
|
void CAddrMan::Serialize(Stream& s_) const
|
||||||
|
{
|
||||||
|
m_impl->Serialize<Stream>(s_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Stream>
|
||||||
|
void CAddrMan::Unserialize(Stream& s_)
|
||||||
|
{
|
||||||
|
m_impl->Unserialize<Stream>(s_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// explicit instantiation
|
||||||
|
template void CAddrMan::Serialize(CHashWriter& s) const;
|
||||||
|
template void CAddrMan::Serialize(CAutoFile& s) const;
|
||||||
|
template void CAddrMan::Serialize(CDataStream& s) const;
|
||||||
|
template void CAddrMan::Unserialize(CAutoFile& s);
|
||||||
|
template void CAddrMan::Unserialize(CHashVerifier<CAutoFile>& s);
|
||||||
|
template void CAddrMan::Unserialize(CDataStream& s);
|
||||||
|
template void CAddrMan::Unserialize(CHashVerifier<CDataStream>& s);
|
||||||
|
|
||||||
|
size_t CAddrMan::size() const
|
||||||
|
{
|
||||||
|
return m_impl->size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CAddrMan::Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty)
|
||||||
|
{
|
||||||
|
return m_impl->Add(vAddr, source, nTimePenalty);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAddrMan::Good(const CService &addr, int64_t nTime)
|
||||||
|
{
|
||||||
|
m_impl->Good(addr, nTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAddrMan::Attempt(const CService &addr, bool fCountFailure, int64_t nTime)
|
||||||
|
{
|
||||||
|
m_impl->Attempt(addr, fCountFailure, nTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAddrMan::ResolveCollisions()
|
||||||
|
{
|
||||||
|
m_impl->ResolveCollisions();
|
||||||
|
}
|
||||||
|
|
||||||
|
CAddrInfo CAddrMan::SelectTriedCollision()
|
||||||
|
{
|
||||||
|
return m_impl->SelectTriedCollision();
|
||||||
|
}
|
||||||
|
|
||||||
|
CAddrInfo CAddrMan::Select(bool newOnly) const
|
||||||
|
{
|
||||||
|
return m_impl->Select(newOnly);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CAddress> CAddrMan::GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
|
||||||
|
{
|
||||||
|
return m_impl->GetAddr(max_addresses, max_pct, network);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAddrMan::Connected(const CService &addr, int64_t nTime)
|
||||||
|
{
|
||||||
|
m_impl->Connected(addr, nTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAddrMan::SetServices(const CService &addr, ServiceFlags nServices)
|
||||||
|
{
|
||||||
|
m_impl->SetServices(addr, nServices);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<bool>& CAddrMan::GetAsmap() const
|
||||||
|
{
|
||||||
|
return m_impl->GetAsmap();
|
||||||
|
}
|
||||||
|
|
188
src/addrman.h
188
src/addrman.h
|
@ -19,6 +19,8 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
class AddrManImpl;
|
||||||
|
|
||||||
/** Default for -checkaddrman */
|
/** Default for -checkaddrman */
|
||||||
static constexpr int32_t DEFAULT_ADDRMAN_CONSISTENCY_CHECKS{0};
|
static constexpr int32_t DEFAULT_ADDRMAN_CONSISTENCY_CHECKS{0};
|
||||||
|
|
||||||
|
@ -53,7 +55,7 @@ private:
|
||||||
//! position in vRandom
|
//! position in vRandom
|
||||||
mutable int nRandomPos{-1};
|
mutable int nRandomPos{-1};
|
||||||
|
|
||||||
friend class CAddrMan;
|
friend class AddrManImpl;
|
||||||
friend class CAddrManDeterministic;
|
friend class CAddrManDeterministic;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -141,42 +143,41 @@ static constexpr int ADDRMAN_BUCKET_SIZE{1 << ADDRMAN_BUCKET_SIZE_LOG2};
|
||||||
*/
|
*/
|
||||||
class CAddrMan
|
class CAddrMan
|
||||||
{
|
{
|
||||||
|
const std::unique_ptr<AddrManImpl> m_impl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit CAddrMan(std::vector<bool> asmap, bool deterministic, int32_t consistency_check_ratio);
|
explicit CAddrMan(std::vector<bool> asmap, bool deterministic, int32_t consistency_check_ratio);
|
||||||
|
|
||||||
~CAddrMan();
|
~CAddrMan();
|
||||||
|
|
||||||
template <typename Stream>
|
template <typename Stream>
|
||||||
void Serialize(Stream& s_) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
void Serialize(Stream& s_) const;
|
||||||
|
|
||||||
template <typename Stream>
|
template <typename Stream>
|
||||||
void Unserialize(Stream& s_) EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
void Unserialize(Stream& s_);
|
||||||
|
|
||||||
//! Return the number of (unique) addresses in all tables.
|
//! Return the number of (unique) addresses in all tables.
|
||||||
size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
size_t size() const;
|
||||||
|
|
||||||
//! Add addresses to addrman's new table.
|
//! Add addresses to addrman's new table.
|
||||||
bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty = 0)
|
bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty = 0);
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
|
||||||
|
|
||||||
//! Mark an entry as accessible.
|
//! Mark an entry as accessible.
|
||||||
void Good(const CService &addr, int64_t nTime = GetAdjustedTime())
|
void Good(const CService &addr, int64_t nTime = GetAdjustedTime());
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
|
||||||
|
|
||||||
//! Mark an entry as connection attempted to.
|
//! Mark an entry as connection attempted to.
|
||||||
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime = GetAdjustedTime())
|
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime = GetAdjustedTime());
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
|
||||||
|
|
||||||
//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
|
//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
|
||||||
void ResolveCollisions() EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
void ResolveCollisions();
|
||||||
|
|
||||||
//! Randomly select an address in tried that another address is attempting to evict.
|
//! Randomly select an address in tried that another address is attempting to evict.
|
||||||
CAddrInfo SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
CAddrInfo SelectTriedCollision();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Choose an address to connect to.
|
* Choose an address to connect to.
|
||||||
*/
|
*/
|
||||||
CAddrInfo Select(bool newOnly = false) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
CAddrInfo Select(bool newOnly = false) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return all or many randomly selected addresses, optionally by network.
|
* Return all or many randomly selected addresses, optionally by network.
|
||||||
|
@ -185,170 +186,15 @@ public:
|
||||||
* @param[in] max_pct Maximum percentage of addresses to return (0 = all).
|
* @param[in] max_pct Maximum percentage of addresses to return (0 = all).
|
||||||
* @param[in] network Select only addresses of this network (nullopt = all).
|
* @param[in] network Select only addresses of this network (nullopt = all).
|
||||||
*/
|
*/
|
||||||
std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
|
std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const;
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
|
||||||
|
|
||||||
//! Outer function for Connected_()
|
//! Outer function for Connected_()
|
||||||
void Connected(const CService &addr, int64_t nTime = GetAdjustedTime())
|
void Connected(const CService &addr, int64_t nTime = GetAdjustedTime());
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
|
||||||
|
|
||||||
void SetServices(const CService &addr, ServiceFlags nServices)
|
void SetServices(const CService &addr, ServiceFlags nServices);
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
|
||||||
|
|
||||||
const std::vector<bool>& GetAsmap() const;
|
const std::vector<bool>& GetAsmap() const;
|
||||||
|
|
||||||
private:
|
|
||||||
//! A mutex to protect the inner data structures.
|
|
||||||
mutable Mutex cs;
|
|
||||||
|
|
||||||
//! Source of random numbers for randomization in inner loops
|
|
||||||
mutable FastRandomContext insecure_rand GUARDED_BY(cs);
|
|
||||||
|
|
||||||
//! secret key to randomize bucket select with
|
|
||||||
uint256 nKey;
|
|
||||||
|
|
||||||
//! Serialization versions.
|
|
||||||
enum Format : uint8_t {
|
|
||||||
V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
|
|
||||||
V1_DETERMINISTIC = 1, //!< for pre-asmap files
|
|
||||||
V2_ASMAP = 2, //!< for files including asmap version
|
|
||||||
V3_BIP155 = 3, //!< same as V2_ASMAP plus addresses are in BIP155 format
|
|
||||||
};
|
|
||||||
|
|
||||||
//! The maximum format this software knows it can unserialize. Also, we always serialize
|
|
||||||
//! in this format.
|
|
||||||
//! The format (first byte in the serialized stream) can be higher than this and
|
|
||||||
//! still this software may be able to unserialize the file - if the second byte
|
|
||||||
//! (see `lowest_compatible` in `Unserialize()`) is less or equal to this.
|
|
||||||
static constexpr Format FILE_FORMAT = Format::V3_BIP155;
|
|
||||||
|
|
||||||
//! The initial value of a field that is incremented every time an incompatible format
|
|
||||||
//! change is made (such that old software versions would not be able to parse and
|
|
||||||
//! understand the new file format). This is 32 because we overtook the "key size"
|
|
||||||
//! field which was 32 historically.
|
|
||||||
//! @note Don't increment this. Increment `lowest_compatible` in `Serialize()` instead.
|
|
||||||
static constexpr uint8_t INCOMPATIBILITY_BASE = 32;
|
|
||||||
|
|
||||||
//! last used nId
|
|
||||||
int nIdCount GUARDED_BY(cs){0};
|
|
||||||
|
|
||||||
//! table with information about all nIds
|
|
||||||
std::unordered_map<int, CAddrInfo> mapInfo GUARDED_BY(cs);
|
|
||||||
|
|
||||||
//! find an nId based on its network address
|
|
||||||
std::unordered_map<CNetAddr, int, CNetAddrHash> 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);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
//! 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);
|
|
||||||
|
|
||||||
//! 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;
|
|
||||||
|
|
||||||
/** Perform consistency checks every m_consistency_check_ratio operations (if non-zero). */
|
|
||||||
const int32_t m_consistency_check_ratio;
|
|
||||||
|
|
||||||
// Compressed IP->ASN mapping, loaded from a file when a node starts.
|
|
||||||
// Should be always empty if no file was provided.
|
|
||||||
// This mapping is then used for bucketing nodes in Addrman.
|
|
||||||
//
|
|
||||||
// If asmap is provided, nodes will be bucketed by
|
|
||||||
// AS they belong to, in order to make impossible for a node
|
|
||||||
// to connect to several nodes hosted in a single AS.
|
|
||||||
// This is done in response to Erebus attack, but also to generally
|
|
||||||
// diversify the connections every node creates,
|
|
||||||
// especially useful when a large fraction of nodes
|
|
||||||
// operate under a couple of cloud providers.
|
|
||||||
//
|
|
||||||
// If a new asmap was provided, the existing records
|
|
||||||
// would be re-bucketed accordingly.
|
|
||||||
const std::vector<bool> m_asmap;
|
|
||||||
|
|
||||||
//! Find an entry.
|
|
||||||
CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! Create a new entry and add it to the internal data structures mapInfo, mapAddr and vRandom.
|
|
||||||
CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *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);
|
|
||||||
|
|
||||||
//! 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(CAddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! Mark an entry "good", possibly moving it from "new" to "tried".
|
|
||||||
void Good_(const CService &addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! Add an entry to the "new" table.
|
|
||||||
bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! Mark an entry as attempted to connect.
|
|
||||||
void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! Select an address to connect to, if newOnly is set to true, only the new table is selected from.
|
|
||||||
CAddrInfo Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return all or many randomly selected addresses, optionally by network.
|
|
||||||
*
|
|
||||||
* @param[out] vAddr Vector of randomly selected addresses from vRandom.
|
|
||||||
* @param[in] max_addresses Maximum number of addresses to return (0 = all).
|
|
||||||
* @param[in] max_pct Maximum percentage of addresses to return (0 = all).
|
|
||||||
* @param[in] network Select only addresses of this network (nullopt = all).
|
|
||||||
*/
|
|
||||||
void GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size_t max_pct, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
/** We have successfully connected to this peer. Calling this function
|
|
||||||
* updates the CAddress's nTime, which is used in our IsTerrible()
|
|
||||||
* decisions and gossiped to peers. Callers should be careful that updating
|
|
||||||
* this information doesn't leak topology information to network spies.
|
|
||||||
*
|
|
||||||
* net_processing calls this function when it *disconnects* from a peer to
|
|
||||||
* not leak information about currently connected peers.
|
|
||||||
*
|
|
||||||
* @param[in] addr The address of the peer we were connected to
|
|
||||||
* @param[in] nTime The time that we were last connected to this peer
|
|
||||||
*/
|
|
||||||
void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! Update an entry's service bits.
|
|
||||||
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
|
|
||||||
void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! Return a random to-be-evicted tried table address.
|
|
||||||
CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! Consistency check, taking into account m_consistency_check_ratio. Will std::abort if an inconsistency is detected.
|
|
||||||
void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
//! Perform consistency check, regardless of m_consistency_check_ratio.
|
|
||||||
//! @returns an error code or zero.
|
|
||||||
int ForceCheckAddrman() const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
|
||||||
|
|
||||||
friend class CAddrManTest;
|
friend class CAddrManTest;
|
||||||
friend class CAddrManDeterministic;
|
friend class CAddrManDeterministic;
|
||||||
};
|
};
|
||||||
|
|
206
src/addrman_impl.h
Normal file
206
src/addrman_impl.h
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
// Copyright (c) 2021 The Bitcoin Core developers
|
||||||
|
// Distributed under the MIT software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#ifndef BITCOIN_ADDRMAN_IMPL_H
|
||||||
|
#define BITCOIN_ADDRMAN_IMPL_H
|
||||||
|
|
||||||
|
class AddrManImpl
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AddrManImpl(std::vector<bool>&& asmap, bool deterministic, int32_t consistency_check_ratio);
|
||||||
|
|
||||||
|
~AddrManImpl();
|
||||||
|
|
||||||
|
template <typename Stream>
|
||||||
|
void Serialize(Stream& s_) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
template <typename Stream>
|
||||||
|
void Unserialize(Stream& s_) EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
void Good(const CService &addr, int64_t nTime)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
void ResolveCollisions() EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
CAddrInfo SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
CAddrInfo Select(bool newOnly) const
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct, std::optional<Network> network) const
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
void Connected(const CService &addr, int64_t nTime)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
void SetServices(const CService &addr, ServiceFlags nServices)
|
||||||
|
EXCLUSIVE_LOCKS_REQUIRED(!cs);
|
||||||
|
|
||||||
|
const std::vector<bool>& GetAsmap() const;
|
||||||
|
|
||||||
|
friend class CAddrManTest;
|
||||||
|
friend class CAddrManDeterministic;
|
||||||
|
|
||||||
|
private:
|
||||||
|
//! A mutex to protect the inner data structures.
|
||||||
|
mutable Mutex cs;
|
||||||
|
|
||||||
|
//! Source of random numbers for randomization in inner loops
|
||||||
|
mutable FastRandomContext insecure_rand GUARDED_BY(cs);
|
||||||
|
|
||||||
|
//! secret key to randomize bucket select with
|
||||||
|
uint256 nKey;
|
||||||
|
|
||||||
|
//! Serialization versions.
|
||||||
|
enum Format : uint8_t {
|
||||||
|
V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
|
||||||
|
V1_DETERMINISTIC = 1, //!< for pre-asmap files
|
||||||
|
V2_ASMAP = 2, //!< for files including asmap version
|
||||||
|
V3_BIP155 = 3, //!< same as V2_ASMAP plus addresses are in BIP155 format
|
||||||
|
};
|
||||||
|
|
||||||
|
//! The maximum format this software knows it can unserialize. Also, we always serialize
|
||||||
|
//! in this format.
|
||||||
|
//! The format (first byte in the serialized stream) can be higher than this and
|
||||||
|
//! still this software may be able to unserialize the file - if the second byte
|
||||||
|
//! (see `lowest_compatible` in `Unserialize()`) is less or equal to this.
|
||||||
|
static constexpr Format FILE_FORMAT = Format::V3_BIP155;
|
||||||
|
|
||||||
|
//! The initial value of a field that is incremented every time an incompatible format
|
||||||
|
//! change is made (such that old software versions would not be able to parse and
|
||||||
|
//! understand the new file format). This is 32 because we overtook the "key size"
|
||||||
|
//! field which was 32 historically.
|
||||||
|
//! @note Don't increment this. Increment `lowest_compatible` in `Serialize()` instead.
|
||||||
|
static constexpr uint8_t INCOMPATIBILITY_BASE = 32;
|
||||||
|
|
||||||
|
//! last used nId
|
||||||
|
int nIdCount GUARDED_BY(cs){0};
|
||||||
|
|
||||||
|
//! table with information about all nIds
|
||||||
|
std::unordered_map<int, CAddrInfo> mapInfo GUARDED_BY(cs);
|
||||||
|
|
||||||
|
//! find an nId based on its network address
|
||||||
|
std::unordered_map<CNetAddr, int, CNetAddrHash> 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
//! 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);
|
||||||
|
|
||||||
|
//! 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;
|
||||||
|
|
||||||
|
/** Perform consistency checks every m_consistency_check_ratio operations (if non-zero). */
|
||||||
|
const int32_t m_consistency_check_ratio;
|
||||||
|
|
||||||
|
// Compressed IP->ASN mapping, loaded from a file when a node starts.
|
||||||
|
// Should be always empty if no file was provided.
|
||||||
|
// This mapping is then used for bucketing nodes in Addrman.
|
||||||
|
//
|
||||||
|
// If asmap is provided, nodes will be bucketed by
|
||||||
|
// AS they belong to, in order to make impossible for a node
|
||||||
|
// to connect to several nodes hosted in a single AS.
|
||||||
|
// This is done in response to Erebus attack, but also to generally
|
||||||
|
// diversify the connections every node creates,
|
||||||
|
// especially useful when a large fraction of nodes
|
||||||
|
// operate under a couple of cloud providers.
|
||||||
|
//
|
||||||
|
// If a new asmap was provided, the existing records
|
||||||
|
// would be re-bucketed accordingly.
|
||||||
|
const std::vector<bool> m_asmap;
|
||||||
|
|
||||||
|
//! Find an entry.
|
||||||
|
CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! Create a new entry and add it to the internal data structures mapInfo, mapAddr and vRandom.
|
||||||
|
CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *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);
|
||||||
|
|
||||||
|
//! 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(CAddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! Mark an entry "good", possibly moving it from "new" to "tried".
|
||||||
|
void Good_(const CService &addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! Add an entry to the "new" table.
|
||||||
|
bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! Mark an entry as attempted to connect.
|
||||||
|
void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! Select an address to connect to, if newOnly is set to true, only the new table is selected from.
|
||||||
|
CAddrInfo Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return all or many randomly selected addresses, optionally by network.
|
||||||
|
*
|
||||||
|
* @param[out] vAddr Vector of randomly selected addresses from vRandom.
|
||||||
|
* @param[in] max_addresses Maximum number of addresses to return (0 = all).
|
||||||
|
* @param[in] max_pct Maximum percentage of addresses to return (0 = all).
|
||||||
|
* @param[in] network Select only addresses of this network (nullopt = all).
|
||||||
|
*/
|
||||||
|
void GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size_t max_pct, std::optional<Network> network) const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
/** We have successfully connected to this peer. Calling this function
|
||||||
|
* updates the CAddress's nTime, which is used in our IsTerrible()
|
||||||
|
* decisions and gossiped to peers. Callers should be careful that updating
|
||||||
|
* this information doesn't leak topology information to network spies.
|
||||||
|
*
|
||||||
|
* net_processing calls this function when it *disconnects* from a peer to
|
||||||
|
* not leak information about currently connected peers.
|
||||||
|
*
|
||||||
|
* @param[in] addr The address of the peer we were connected to
|
||||||
|
* @param[in] nTime The time that we were last connected to this peer
|
||||||
|
*/
|
||||||
|
void Connected_(const CService& addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! Update an entry's service bits.
|
||||||
|
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
|
||||||
|
void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! Return a random to-be-evicted tried table address.
|
||||||
|
CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! Consistency check, taking into account m_consistency_check_ratio. Will std::abort if an inconsistency is detected.
|
||||||
|
void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
|
||||||
|
//! Perform consistency check, regardless of m_consistency_check_ratio.
|
||||||
|
//! @returns an error code or zero.
|
||||||
|
int ForceCheckAddrman() const EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // BITCOIN_ADDRMAN_IMPL_H
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <addrdb.h>
|
#include <addrdb.h>
|
||||||
#include <addrman.h>
|
#include <addrman.h>
|
||||||
|
#include <addrman_impl.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
#include <clientversion.h>
|
#include <clientversion.h>
|
||||||
#include <hash.h>
|
#include <hash.h>
|
||||||
|
@ -90,30 +91,30 @@ public:
|
||||||
|
|
||||||
CAddrInfo* Find(const CNetAddr& addr, int* pnId = nullptr)
|
CAddrInfo* Find(const CNetAddr& addr, int* pnId = nullptr)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(m_impl->cs);
|
||||||
return CAddrMan::Find(addr, pnId);
|
return m_impl->Find(addr, pnId);
|
||||||
}
|
}
|
||||||
|
|
||||||
CAddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr)
|
CAddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(m_impl->cs);
|
||||||
return CAddrMan::Create(addr, addrSource, pnId);
|
return m_impl->Create(addr, addrSource, pnId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Delete(int nId)
|
void Delete(int nId)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(m_impl->cs);
|
||||||
CAddrMan::Delete(nId);
|
m_impl->Delete(nId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used to test deserialization
|
// Used to test deserialization
|
||||||
std::pair<int, int> GetBucketAndEntry(const CAddress& addr)
|
std::pair<int, int> GetBucketAndEntry(const CAddress& addr)
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(m_impl->cs);
|
||||||
int nId = mapAddr[addr];
|
int nId = m_impl->mapAddr[addr];
|
||||||
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; ++bucket) {
|
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; ++bucket) {
|
||||||
for (int entry = 0; entry < ADDRMAN_BUCKET_SIZE; ++entry) {
|
for (int entry = 0; entry < ADDRMAN_BUCKET_SIZE; ++entry) {
|
||||||
if (nId == vvNew[bucket][entry]) {
|
if (nId == m_impl->vvNew[bucket][entry]) {
|
||||||
return std::pair<int, int>(bucket, entry);
|
return std::pair<int, int>(bucket, entry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <addrdb.h>
|
#include <addrdb.h>
|
||||||
#include <addrman.h>
|
#include <addrman.h>
|
||||||
|
#include <addrman_impl.h>
|
||||||
#include <chainparams.h>
|
#include <chainparams.h>
|
||||||
#include <merkleblock.h>
|
#include <merkleblock.h>
|
||||||
#include <test/fuzz/FuzzedDataProvider.h>
|
#include <test/fuzz/FuzzedDataProvider.h>
|
||||||
|
@ -43,13 +44,13 @@ public:
|
||||||
: CAddrMan(std::move(asmap), /* deterministic */ true, /* consistency_check_ratio */ 0)
|
: CAddrMan(std::move(asmap), /* deterministic */ true, /* consistency_check_ratio */ 0)
|
||||||
, m_fuzzed_data_provider(fuzzed_data_provider)
|
, m_fuzzed_data_provider(fuzzed_data_provider)
|
||||||
{
|
{
|
||||||
WITH_LOCK(cs, insecure_rand = FastRandomContext{ConsumeUInt256(fuzzed_data_provider)});
|
WITH_LOCK(m_impl->cs, m_impl->insecure_rand = FastRandomContext{ConsumeUInt256(fuzzed_data_provider)});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a random address. Always returns a valid address.
|
* Generate a random address. Always returns a valid address.
|
||||||
*/
|
*/
|
||||||
CNetAddr RandAddr() EXCLUSIVE_LOCKS_REQUIRED(cs)
|
CNetAddr RandAddr() EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs)
|
||||||
{
|
{
|
||||||
CNetAddr addr;
|
CNetAddr addr;
|
||||||
if (m_fuzzed_data_provider.remaining_bytes() > 1 && m_fuzzed_data_provider.ConsumeBool()) {
|
if (m_fuzzed_data_provider.remaining_bytes() > 1 && m_fuzzed_data_provider.ConsumeBool()) {
|
||||||
|
@ -61,7 +62,7 @@ public:
|
||||||
{4, ADDR_TORV3_SIZE},
|
{4, ADDR_TORV3_SIZE},
|
||||||
{5, ADDR_I2P_SIZE},
|
{5, ADDR_I2P_SIZE},
|
||||||
{6, ADDR_CJDNS_SIZE}};
|
{6, ADDR_CJDNS_SIZE}};
|
||||||
uint8_t net = insecure_rand.randrange(5) + 1; // [1..5]
|
uint8_t net = m_impl->insecure_rand.randrange(5) + 1; // [1..5]
|
||||||
if (net == 3) {
|
if (net == 3) {
|
||||||
net = 6;
|
net = 6;
|
||||||
}
|
}
|
||||||
|
@ -69,7 +70,7 @@ public:
|
||||||
CDataStream s(SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
|
CDataStream s(SER_NETWORK, PROTOCOL_VERSION | ADDRV2_FORMAT);
|
||||||
|
|
||||||
s << net;
|
s << net;
|
||||||
s << insecure_rand.randbytes(net_len_map.at(net));
|
s << m_impl->insecure_rand.randbytes(net_len_map.at(net));
|
||||||
|
|
||||||
s >> addr;
|
s >> addr;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +90,7 @@ public:
|
||||||
*/
|
*/
|
||||||
void Fill()
|
void Fill()
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
LOCK(m_impl->cs);
|
||||||
|
|
||||||
// Add some of the addresses directly to the "tried" table.
|
// Add some of the addresses directly to the "tried" table.
|
||||||
|
|
||||||
|
@ -102,20 +103,20 @@ public:
|
||||||
// the latter is exhausted it just returns 0.
|
// the latter is exhausted it just returns 0.
|
||||||
for (size_t i = 0; i < num_sources; ++i) {
|
for (size_t i = 0; i < num_sources; ++i) {
|
||||||
const auto source = RandAddr();
|
const auto source = RandAddr();
|
||||||
const size_t num_addresses = insecure_rand.randrange(500) + 1; // [1..500]
|
const size_t num_addresses = m_impl->insecure_rand.randrange(500) + 1; // [1..500]
|
||||||
|
|
||||||
for (size_t j = 0; j < num_addresses; ++j) {
|
for (size_t j = 0; j < num_addresses; ++j) {
|
||||||
const auto addr = CAddress{CService{RandAddr(), 8333}, NODE_NETWORK};
|
const auto addr = CAddress{CService{RandAddr(), 8333}, NODE_NETWORK};
|
||||||
const auto time_penalty = insecure_rand.randrange(100000001);
|
const auto time_penalty = m_impl->insecure_rand.randrange(100000001);
|
||||||
Add_(addr, source, time_penalty);
|
m_impl->Add_(addr, source, time_penalty);
|
||||||
|
|
||||||
if (n > 0 && mapInfo.size() % n == 0) {
|
if (n > 0 && m_impl->mapInfo.size() % n == 0) {
|
||||||
Good_(addr, false, GetTime());
|
m_impl->Good_(addr, false, GetTime());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add 10% of the addresses from more than one source.
|
// Add 10% of the addresses from more than one source.
|
||||||
if (insecure_rand.randrange(10) == 0 && prev_source.IsValid()) {
|
if (m_impl->insecure_rand.randrange(10) == 0 && prev_source.IsValid()) {
|
||||||
Add_(addr, prev_source, time_penalty);
|
m_impl->Add_({addr}, prev_source, time_penalty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prev_source = source;
|
prev_source = source;
|
||||||
|
@ -131,10 +132,10 @@ public:
|
||||||
*/
|
*/
|
||||||
bool operator==(const CAddrManDeterministic& other)
|
bool operator==(const CAddrManDeterministic& other)
|
||||||
{
|
{
|
||||||
LOCK2(cs, other.cs);
|
LOCK2(m_impl->cs, other.m_impl->cs);
|
||||||
|
|
||||||
if (mapInfo.size() != other.mapInfo.size() || nNew != other.nNew ||
|
if (m_impl->mapInfo.size() != other.m_impl->mapInfo.size() || m_impl->nNew != other.m_impl->nNew ||
|
||||||
nTried != other.nTried) {
|
m_impl->nTried != other.m_impl->nTried) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,15 +161,15 @@ public:
|
||||||
|
|
||||||
using Addresses = std::unordered_set<CAddrInfo, CAddrInfoHasher, CAddrInfoEq>;
|
using Addresses = std::unordered_set<CAddrInfo, CAddrInfoHasher, CAddrInfoEq>;
|
||||||
|
|
||||||
const size_t num_addresses{mapInfo.size()};
|
const size_t num_addresses{m_impl->mapInfo.size()};
|
||||||
|
|
||||||
Addresses addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
|
Addresses addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
|
||||||
for (const auto& [id, addr] : mapInfo) {
|
for (const auto& [id, addr] : m_impl->mapInfo) {
|
||||||
addresses.insert(addr);
|
addresses.insert(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Addresses other_addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
|
Addresses other_addresses{num_addresses, addrinfo_hasher, addrinfo_eq};
|
||||||
for (const auto& [id, addr] : other.mapInfo) {
|
for (const auto& [id, addr] : other.m_impl->mapInfo) {
|
||||||
other_addresses.insert(addr);
|
other_addresses.insert(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,14 +177,14 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto IdsReferToSameAddress = [&](int id, int other_id) EXCLUSIVE_LOCKS_REQUIRED(cs, other.cs) {
|
auto IdsReferToSameAddress = [&](int id, int other_id) EXCLUSIVE_LOCKS_REQUIRED(m_impl->cs, other.m_impl->cs) {
|
||||||
if (id == -1 && other_id == -1) {
|
if (id == -1 && other_id == -1) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if ((id == -1 && other_id != -1) || (id != -1 && other_id == -1)) {
|
if ((id == -1 && other_id != -1) || (id != -1 && other_id == -1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return mapInfo.at(id) == other.mapInfo.at(other_id);
|
return m_impl->mapInfo.at(id) == other.m_impl->mapInfo.at(other_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Check that `vvNew` contains the same addresses as `other.vvNew`. Notice - `vvNew[i][j]`
|
// Check that `vvNew` contains the same addresses as `other.vvNew`. Notice - `vvNew[i][j]`
|
||||||
|
@ -191,7 +192,7 @@ public:
|
||||||
// themselves may differ between `vvNew` and `other.vvNew`.
|
// themselves may differ between `vvNew` and `other.vvNew`.
|
||||||
for (size_t i = 0; i < ADDRMAN_NEW_BUCKET_COUNT; ++i) {
|
for (size_t i = 0; i < ADDRMAN_NEW_BUCKET_COUNT; ++i) {
|
||||||
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
|
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
|
||||||
if (!IdsReferToSameAddress(vvNew[i][j], other.vvNew[i][j])) {
|
if (!IdsReferToSameAddress(m_impl->vvNew[i][j], other.m_impl->vvNew[i][j])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,7 +201,7 @@ public:
|
||||||
// Same for `vvTried`.
|
// Same for `vvTried`.
|
||||||
for (size_t i = 0; i < ADDRMAN_TRIED_BUCKET_COUNT; ++i) {
|
for (size_t i = 0; i < ADDRMAN_TRIED_BUCKET_COUNT; ++i) {
|
||||||
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
|
for (size_t j = 0; j < ADDRMAN_BUCKET_SIZE; ++j) {
|
||||||
if (!IdsReferToSameAddress(vvTried[i][j], other.vvTried[i][j])) {
|
if (!IdsReferToSameAddress(m_impl->vvTried[i][j], other.m_impl->vvTried[i][j])) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue