merge bitcoin#26847: track AddrMan totals by network and table, improve precision of adding fixed seeds

This commit is contained in:
Kittywhiskers Van Gogh 2024-09-02 09:28:47 +00:00
parent 79a550ec15
commit 2e9b48a910
No known key found for this signature in database
GPG Key ID: 30CD0C065E5C4AAD
8 changed files with 182 additions and 62 deletions

View File

@ -192,7 +192,7 @@ std::optional<bilingual_str> LoadAddrman(const NetGroupManager& netgroupman, con
const auto path_addr{gArgs.GetDataDirNet() / "peers.dat"};
try {
DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->size(), GetTimeMillis() - nStart);
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman->Size(), GetTimeMillis() - nStart);
} catch (const DbNotFoundError&) {
// Addrman can be in an inconsistent state after failure, reset it
addrman = std::make_unique<AddrMan>(netgroupman, /*deterministic=*/false, /*consistency_check_ratio=*/check_addrman);

View File

@ -282,6 +282,7 @@ void AddrManImpl::Unserialize(Stream& s_)
mapAddr[info] = n;
info.nRandomPos = vRandom.size();
vRandom.push_back(n);
m_network_counts[info.GetNetwork()].n_new++;
}
nIdCount = nNew;
@ -301,6 +302,7 @@ void AddrManImpl::Unserialize(Stream& s_)
mapAddr[info] = nIdCount;
vvTried[nKBucket][nKBucketPos] = nIdCount;
nIdCount++;
m_network_counts[info.GetNetwork()].n_tried++;
} else {
nLost++;
}
@ -414,6 +416,8 @@ AddrInfo* AddrManImpl::Create(const CAddress& addr, const CNetAddr& addrSource,
mapAddr[addr] = nId;
mapInfo[nId].nRandomPos = vRandom.size();
vRandom.push_back(nId);
nNew++;
m_network_counts[addr.GetNetwork()].n_new++;
if (pnId)
*pnId = nId;
return &mapInfo[nId];
@ -453,6 +457,7 @@ void AddrManImpl::Delete(int nId)
assert(info.nRefCount == 0);
SwapRandom(info.nRandomPos, vRandom.size() - 1);
m_network_counts[info.GetNetwork()].n_new--;
vRandom.pop_back();
mapAddr.erase(info);
mapInfo.erase(nId);
@ -493,6 +498,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
}
}
nNew--;
m_network_counts[info.GetNetwork()].n_new--;
assert(info.nRefCount == 0);
@ -511,6 +517,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
infoOld.fInTried = false;
vvTried[nKBucket][nKBucketPos] = -1;
nTried--;
m_network_counts[infoOld.GetNetwork()].n_tried--;
// find which new bucket it belongs to
int nUBucket = infoOld.GetNewBucket(nKey, m_netgroupman);
@ -522,6 +529,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
infoOld.nRefCount = 1;
vvNew[nUBucket][nUBucketPos] = nIdEvict;
nNew++;
m_network_counts[infoOld.GetNetwork()].n_new++;
LogPrint(BCLog::ADDRMAN, "Moved %s from tried[%i][%i] to new[%i][%i] to make space\n",
infoOld.ToString(), nKBucket, nKBucketPos, nUBucket, nUBucketPos);
}
@ -530,6 +538,7 @@ void AddrManImpl::MakeTried(AddrInfo& info, int nId)
vvTried[nKBucket][nKBucketPos] = nId;
nTried++;
info.fInTried = true;
m_network_counts[info.GetNetwork()].n_tried++;
}
bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
@ -580,7 +589,6 @@ bool AddrManImpl::AddSingle(const CAddress& addr, const CNetAddr& source, int64_
} else {
pinfo = Create(addr, source, &nId);
pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
nNew++;
}
int nUBucket = pinfo->GetNewBucket(nKey, source, m_netgroupman);
@ -965,6 +973,28 @@ std::optional<AddressPosition> AddrManImpl::FindAddressEntry_(const CAddress& ad
}
}
size_t AddrManImpl::Size_(std::optional<Network> net, std::optional<bool> in_new) const
{
AssertLockHeld(cs);
if (!net.has_value()) {
if (in_new.has_value()) {
return *in_new ? nNew : nTried;
} else {
return vRandom.size();
}
}
if (auto it = m_network_counts.find(*net); it != m_network_counts.end()) {
auto net_count = it->second;
if (in_new.has_value()) {
return *in_new ? net_count.n_new : net_count.n_tried;
} else {
return net_count.n_new + net_count.n_tried;
}
}
return 0;
}
void AddrManImpl::Check() const
{
AssertLockHeld(cs);
@ -989,6 +1019,7 @@ int AddrManImpl::CheckAddrman() const
std::unordered_set<int> setTried;
std::unordered_map<int, int> mapNew;
std::unordered_map<Network, NewTriedCount> local_counts;
if (vRandom.size() != (size_t)(nTried + nNew))
return -7;
@ -1002,12 +1033,14 @@ int AddrManImpl::CheckAddrman() const
if (info.nRefCount)
return -2;
setTried.insert(n);
local_counts[info.GetNetwork()].n_tried++;
} else {
if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
return -3;
if (!info.nRefCount)
return -4;
mapNew[n] = info.nRefCount;
local_counts[info.GetNetwork()].n_new++;
}
const auto it{mapAddr.find(info)};
if (it == mapAddr.end() || it->second != n) {
@ -1065,13 +1098,27 @@ int AddrManImpl::CheckAddrman() const
if (nKey.IsNull())
return -16;
// It's possible that m_network_counts may have all-zero entries that local_counts
// doesn't have if addrs from a network were being added and then removed again in the past.
if (m_network_counts.size() < local_counts.size()) {
return -20;
}
for (const auto& [net, count] : m_network_counts) {
if (local_counts[net].n_new != count.n_new || local_counts[net].n_tried != count.n_tried) {
return -21;
}
}
return 0;
}
size_t AddrManImpl::size() const
size_t AddrManImpl::Size(std::optional<Network> net, std::optional<bool> in_new) const
{
LOCK(cs); // TODO: Cache this in an atomic to avoid this overhead
return vRandom.size();
LOCK(cs);
Check();
auto ret = Size_(net, in_new);
Check();
return ret;
}
bool AddrManImpl::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
@ -1197,9 +1244,9 @@ template void AddrMan::Unserialize(CHashVerifier<CAutoFile>& s);
template void AddrMan::Unserialize(CDataStream& s);
template void AddrMan::Unserialize(CHashVerifier<CDataStream>& s);
size_t AddrMan::size() const
size_t AddrMan::Size(std::optional<Network> net, std::optional<bool> in_new) const
{
return m_impl->size();
return m_impl->Size(net, in_new);
}
bool AddrMan::Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)

View File

@ -110,8 +110,14 @@ public:
template <typename Stream>
void Unserialize(Stream& s_);
//! Return the number of (unique) addresses in all tables.
size_t size() const;
/**
* Return size information about addrman.
*
* @param[in] net Select addresses only from specified network (nullopt = all)
* @param[in] in_new Select addresses only from one table (true = new, false = tried, nullopt = both)
* @return Number of unique addresses that match specified options.
*/
size_t Size(std::optional<Network> net = {}, std::optional<bool> in_new = {}) const;
/**
* Attempt to add one or more addresses to addrman's new table.

View File

@ -110,7 +110,7 @@ public:
template <typename Stream>
void Unserialize(Stream& s_) EXCLUSIVE_LOCKS_REQUIRED(!cs);
size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
size_t Size(std::optional<Network> net, std::optional<bool> in_new) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
bool Add(const std::vector<CAddress>& vAddr, const CNetAddr& source, int64_t nTimePenalty)
EXCLUSIVE_LOCKS_REQUIRED(!cs);
@ -216,6 +216,14 @@ private:
/** Reference to the netgroup manager. netgroupman must be constructed before addrman and destructed after. */
const NetGroupManager& m_netgroupman;
struct NewTriedCount {
size_t n_new;
size_t n_tried;
};
/** Number of entries in addrman per network and new/tried table. */
std::unordered_map<Network, NewTriedCount> m_network_counts GUARDED_BY(cs);
//! Find an entry.
AddrInfo* Find(const CService& addr, int* pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
@ -260,6 +268,8 @@ private:
std::optional<AddressPosition> FindAddressEntry_(const CAddress& addr) EXCLUSIVE_LOCKS_REQUIRED(cs);
size_t Size_(std::optional<Network> net, std::optional<bool> in_new) const 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);

View File

@ -2404,7 +2404,7 @@ void CConnman::ThreadDNSAddressSeed()
if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) {
// When -forcednsseed is provided, query all.
seeds_right_now = seeds.size();
} else if (addrman.size() == 0) {
} else if (addrman.Size() == 0) {
// If we have no known peers, query all.
// This will occur on the first run, or if peers.dat has been
// deleted.
@ -2423,13 +2423,13 @@ void CConnman::ThreadDNSAddressSeed()
// * If we continue having problems, eventually query all the
// DNS seeds, and if that fails too, also try the fixed seeds.
// (done in ThreadOpenConnections)
const std::chrono::seconds seeds_wait_time = (addrman.size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
const std::chrono::seconds seeds_wait_time = (addrman.Size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
for (const std::string& seed : seeds) {
if (seeds_right_now == 0) {
seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE;
if (addrman.size() > 0) {
if (addrman.Size() > 0) {
LogPrintf("Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
std::chrono::seconds to_wait = seeds_wait_time;
while (to_wait.count() > 0) {
@ -2513,7 +2513,7 @@ void CConnman::DumpAddresses()
DumpPeerAddresses(::gArgs, addrman);
LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat %dms\n",
addrman.size(), GetTimeMillis() - nStart);
addrman.Size(), GetTimeMillis() - nStart);
}
void CConnman::ProcessAddrFetch()
@ -2583,6 +2583,19 @@ int CConnman::GetExtraBlockRelayCount() const
return std::max(block_relay_peers - m_max_outbound_block_relay, 0);
}
std::unordered_set<Network> CConnman::GetReachableEmptyNetworks() const
{
std::unordered_set<Network> networks{};
for (int n = 0; n < NET_MAX; n++) {
enum Network net = (enum Network)n;
if (net == NET_UNROUTABLE || net == NET_INTERNAL) continue;
if (IsReachable(net) && addrman.Size(net, std::nullopt) == 0) {
networks.insert(net);
}
}
return networks;
}
void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDeterministicMNManager& dmnman)
{
AssertLockNotHeld(m_unused_i2p_sessions_mutex);
@ -2631,7 +2644,8 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
if (interruptNet)
return;
if (add_fixed_seeds && addrman.size() == 0) {
const std::unordered_set<Network> fixed_seed_networks{GetReachableEmptyNetworks()};
if (add_fixed_seeds && !fixed_seed_networks.empty()) {
// When the node starts with an empty peers.dat, there are a few other sources of peers before
// we fallback on to fixed seeds: -dnsseed, -seednode, -addnode
// If none of those are available, we fallback on to fixed seeds immediately, else we allow
@ -2640,7 +2654,7 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
// It is cheapest to check if enough time has passed first.
if (GetTime<std::chrono::seconds>() > start + std::chrono::minutes{1}) {
add_fixed_seeds_now = true;
LogPrintf("Adding fixed seeds as 60 seconds have passed and addrman is empty\n");
LogPrintf("Adding fixed seeds as 60 seconds have passed and addrman is empty for at least one reachable network\n");
}
// Checking !dnsseed is cheaper before locking 2 mutexes.
@ -2657,13 +2671,11 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect, CDe
// We will not make outgoing connections to peers that are unreachable
// (e.g. because of -onlynet configuration).
// Therefore, we do not add them to addrman in the first place.
// Note that if you change -onlynet setting from one network to another,
// peers.dat will contain only peers of unreachable networks and
// manual intervention will be needed (either delete peers.dat after
// configuration change or manually add some reachable peer using addnode),
// see <https://github.com/bitcoin/bitcoin/issues/26035> for details.
// In case previously unreachable networks become reachable
// (e.g. in case of -onlynet changes by the user), fixed seeds will
// be loaded only for networks for which we have no addressses.
seed_addrs.erase(std::remove_if(seed_addrs.begin(), seed_addrs.end(),
[](const CAddress& addr) { return !IsReachable(addr); }),
[&fixed_seed_networks](const CAddress& addr) { return fixed_seed_networks.count(addr.GetNetwork()) == 0; }),
seed_addrs.end());
CNetAddr local;
local.SetInternal("fixedseeds");

View File

@ -45,6 +45,7 @@
#include <optional>
#include <queue>
#include <thread>
#include <unordered_set>
#include <vector>
class CConnman;
@ -1476,6 +1477,12 @@ private:
void RecordBytesRecv(uint64_t bytes);
void RecordBytesSent(uint64_t bytes) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex);
/**
Return reachable networks for which we have no addresses in addrman and therefore
may require loading fixed seeds.
*/
std::unordered_set<Network> GetReachableEmptyNetworks() const;
/**
* Return vector of current BLOCK_RELAY peers.
*/

View File

@ -65,14 +65,14 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
CNetAddr source = ResolveIP("252.2.2.2");
// Test: Does Addrman respond correctly when empty.
BOOST_CHECK_EQUAL(addrman->size(), 0U);
BOOST_CHECK_EQUAL(addrman->Size(), 0U);
auto addr_null = addrman->Select().first;
BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
// Test: Does Addrman::Add work as expected.
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
auto addr_ret1 = addrman->Select().first;
BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
@ -80,7 +80,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
// Expected dup IP should not be added.
CService addr1_dup = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(!addrman->Add({CAddress(addr1_dup, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// Test: New table has one addr and we add a diff addr we should
@ -91,7 +91,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
CService addr2 = ResolveService("250.1.1.2", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
BOOST_CHECK(addrman->size() >= 1);
BOOST_CHECK(addrman->Size() >= 1);
// Test: reset addrman and test AddrMan::Add multiple addresses works as expected
addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
BOOST_CHECK(addrman->Add(vAddr, source));
BOOST_CHECK(addrman->size() >= 1);
BOOST_CHECK(addrman->Size() >= 1);
}
BOOST_AUTO_TEST_CASE(addrman_ports)
@ -108,23 +108,23 @@ BOOST_AUTO_TEST_CASE(addrman_ports)
CNetAddr source = ResolveIP("252.2.2.2");
BOOST_CHECK_EQUAL(addrman->size(), 0U);
BOOST_CHECK_EQUAL(addrman->Size(), 0U);
// Test 7; Addr with same IP but diff port does not replace existing addr.
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
CService addr1_port = ResolveService("250.1.1.1", 8334);
BOOST_CHECK(addrman->Add({CAddress(addr1_port, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 2U);
BOOST_CHECK_EQUAL(addrman->Size(), 2U);
auto addr_ret2 = addrman->Select().first;
BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333" || addr_ret2.ToString() == "250.1.1.1:8334");
// Test: Add same IP but diff port to tried table; this converts the entry with
// the specified port to tried, but not the other.
addrman->Good(CAddress(addr1_port, NODE_NONE));
BOOST_CHECK_EQUAL(addrman->size(), 2U);
BOOST_CHECK_EQUAL(addrman->Size(), 2U);
bool newOnly = true;
auto addr_ret3 = addrman->Select(newOnly).first;
BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
@ -139,7 +139,7 @@ BOOST_AUTO_TEST_CASE(addrman_select)
// Test: Select from new with 1 addr in new.
CService addr1 = ResolveService("250.1.1.1", 8333);
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
bool newOnly = true;
auto addr_ret1 = addrman->Select(newOnly).first;
@ -147,14 +147,14 @@ BOOST_AUTO_TEST_CASE(addrman_select)
// Test: move addr to tried, select from new expected nothing returned.
BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
auto addr_ret2 = addrman->Select(newOnly).first;
BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0");
auto addr_ret3 = addrman->Select().first;
BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// Add three addresses to new table.
@ -179,7 +179,7 @@ BOOST_AUTO_TEST_CASE(addrman_select)
BOOST_CHECK(addrman->Good(CAddress(addr7, NODE_NONE)));
// Test: 6 addrs + 1 addr from last test = 7.
BOOST_CHECK_EQUAL(addrman->size(), 7U);
BOOST_CHECK_EQUAL(addrman->Size(), 7U);
// Test: Select pulls from new and tried regardless of port number.
std::set<uint16_t> ports;
@ -197,25 +197,25 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
uint32_t num_addrs{0};
BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
while (num_addrs < 22) { // Magic number! 250.1.1.1 - 250.1.1.22 do not collide with deterministic key = 1
CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
// Test: No collision in new table yet.
BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
}
// Test: new table collision!
CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
uint32_t collisions{1};
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), num_addrs - collisions);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
BOOST_CHECK_EQUAL(addrman->size(), num_addrs - collisions);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
}
BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
@ -233,7 +233,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
}
AddressPosition addr_pos = addrman->FindAddressEntry(addr).value();
BOOST_CHECK_EQUAL(addr_pos.multiplicity, 1U);
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// if nTime increases, an addr can occur in up to 8 buckets
// The acceptance probability decreases exponentially with existing multiplicity -
@ -247,7 +247,7 @@ BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
AddressPosition addr_pos_multi = addrman->FindAddressEntry(addr).value();
BOOST_CHECK_EQUAL(addr_pos_multi.multiplicity, 8U);
// multiplicity doesn't affect size
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
}
BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
@ -258,7 +258,7 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
uint32_t num_addrs{0};
BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
while (num_addrs < 35) { // Magic number! 250.1.1.1 - 250.1.1.35 do not collide in tried with deterministic key = 1
CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
@ -287,7 +287,7 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
// Test: Sanity check, GetAddr should never return anything if addrman
// is empty.
BOOST_CHECK_EQUAL(addrman->size(), 0U);
BOOST_CHECK_EQUAL(addrman->Size(), 0U);
std::vector<CAddress> vAddr1 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
@ -333,11 +333,11 @@ BOOST_AUTO_TEST_CASE(addrman_getaddr)
}
std::vector<CAddress> vAddr = addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt);
size_t percent23 = (addrman->size() * 23) / 100;
size_t percent23 = (addrman->Size() * 23) / 100;
BOOST_CHECK_EQUAL(vAddr.size(), percent23);
BOOST_CHECK_EQUAL(vAddr.size(), 461U);
// (Addrman.size() < number of addresses added) due to address collisions.
BOOST_CHECK_EQUAL(addrman->size(), 2006U);
// (addrman.Size() < number of addresses added) due to address collisions.
BOOST_CHECK_EQUAL(addrman->Size(), 2006U);
}
@ -678,7 +678,7 @@ BOOST_AUTO_TEST_CASE(remove_invalid)
addrman->Add({new1, tried1, new2, tried2}, CNetAddr{});
addrman->Good(tried1);
addrman->Good(tried2);
BOOST_REQUIRE_EQUAL(addrman->size(), 4);
BOOST_REQUIRE_EQUAL(addrman->Size(), 4);
stream << *addrman;
@ -701,14 +701,14 @@ BOOST_AUTO_TEST_CASE(remove_invalid)
addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
stream >> *addrman;
BOOST_CHECK_EQUAL(addrman->size(), 2);
BOOST_CHECK_EQUAL(addrman->Size(), 2);
}
BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
BOOST_CHECK(addrman->size() == 0);
BOOST_CHECK(addrman->Size() == 0);
// Empty addrman should return blank addrman info.
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
@ -793,7 +793,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
BOOST_CHECK(addrman->size() == 0);
BOOST_CHECK(addrman->Size() == 0);
// Empty addrman should return blank addrman info.
BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
@ -875,14 +875,14 @@ BOOST_AUTO_TEST_CASE(load_addrman)
BOOST_CHECK(Lookup("252.5.1.1", source, 8333, false));
std::vector<CAddress> addresses{CAddress(addr1, NODE_NONE), CAddress(addr2, NODE_NONE), CAddress(addr3, NODE_NONE)};
BOOST_CHECK(addrman.Add(addresses, source));
BOOST_CHECK(addrman.size() == 3);
BOOST_CHECK(addrman.Size() == 3);
// Test that the de-serialization does not throw an exception.
CDataStream ssPeers1 = AddrmanToStream(addrman);
bool exceptionThrown = false;
AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
BOOST_CHECK(addrman1.size() == 0);
BOOST_CHECK(addrman1.Size() == 0);
try {
unsigned char pchMsgTmp[4];
ssPeers1 >> pchMsgTmp;
@ -891,16 +891,16 @@ BOOST_AUTO_TEST_CASE(load_addrman)
exceptionThrown = true;
}
BOOST_CHECK(addrman1.size() == 3);
BOOST_CHECK(addrman1.Size() == 3);
BOOST_CHECK(exceptionThrown == false);
// Test that ReadFromStream creates an addrman with the correct number of addrs.
CDataStream ssPeers2 = AddrmanToStream(addrman);
AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
BOOST_CHECK(addrman2.size() == 0);
BOOST_CHECK(addrman2.Size() == 0);
ReadFromStream(addrman2, ssPeers2);
BOOST_CHECK(addrman2.size() == 3);
BOOST_CHECK(addrman2.Size() == 3);
}
// Produce a corrupt peers.dat that claims 20 addrs when it only has one addr.
@ -936,7 +936,7 @@ BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
CDataStream ssPeers1 = MakeCorruptPeersDat();
bool exceptionThrown = false;
AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
BOOST_CHECK(addrman1.size() == 0);
BOOST_CHECK(addrman1.Size() == 0);
try {
unsigned char pchMsgTmp[4];
ssPeers1 >> pchMsgTmp;
@ -945,14 +945,14 @@ BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
exceptionThrown = true;
}
// Even though de-serialization failed addrman is not left in a clean state.
BOOST_CHECK(addrman1.size() == 1);
BOOST_CHECK(addrman1.Size() == 1);
BOOST_CHECK(exceptionThrown);
// Test that ReadFromStream fails if peers.dat is corrupt
CDataStream ssPeers2 = MakeCorruptPeersDat();
AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
BOOST_CHECK(addrman2.size() == 0);
BOOST_CHECK(addrman2.Size() == 0);
BOOST_CHECK_THROW(ReadFromStream(addrman2, ssPeers2), std::ios_base::failure);
}
@ -966,7 +966,7 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
int64_t start_time{GetAdjustedTime() - 10000};
addr.nTime = start_time;
BOOST_CHECK(addrman->Add({addr}, source));
BOOST_CHECK_EQUAL(addrman->size(), 1U);
BOOST_CHECK_EQUAL(addrman->Size(), 1U);
// Updating an addrman entry with a different port doesn't change it
CAddress addr_diff_port{CAddress(ResolveService("250.1.1.1", 8334), NODE_NONE)};
@ -987,4 +987,42 @@ BOOST_AUTO_TEST_CASE(addrman_update_address)
BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);
}
BOOST_AUTO_TEST_CASE(addrman_size)
{
auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
const CNetAddr source = ResolveIP("252.2.2.2");
// empty addrman
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 0U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 0U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 0U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 0U);
// add two ipv4 addresses, one to tried and new
const CAddress addr1{ResolveService("250.1.1.1", 8333), NODE_NONE};
BOOST_CHECK(addrman->Add({addr1}, source));
BOOST_CHECK(addrman->Good(addr1));
const CAddress addr2{ResolveService("250.1.1.2", 8333), NODE_NONE};
BOOST_CHECK(addrman->Add({addr2}, source));
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 2U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/true), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 1U);
// add one i2p address to new
CService i2p_addr;
i2p_addr.SetSpecial("UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P");
const CAddress addr3{i2p_addr, NODE_NONE};
BOOST_CHECK(addrman->Add({addr3}, source));
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 3U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/std::nullopt), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/true), 1U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 2U);
BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
}
BOOST_AUTO_TEST_SUITE_END()

View File

@ -116,7 +116,7 @@ void FillAddrman(AddrMan& addrman, FuzzedDataProvider& fuzzed_data_provider)
const auto time_penalty = fast_random_context.randrange(100000001);
addrman.Add({addr}, source, time_penalty);
if (n > 0 && addrman.size() % n == 0) {
if (n > 0 && addrman.Size() % n == 0) {
addrman.Good(addr, GetTime());
}
@ -306,7 +306,7 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman)
}
});
}
(void)addr_man.size();
(void)addr_man.Size();
CDataStream data_stream(SER_NETWORK, PROTOCOL_VERSION);
data_stream << addr_man;
}