aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/addrman.cpp26
-rw-r--r--src/addrman.h30
-rw-r--r--src/bench/addrman.cpp16
-rw-r--r--src/init.cpp6
-rw-r--r--src/net_processing.cpp19
-rw-r--r--src/rpc/net.cpp2
-rw-r--r--src/test/addrman_tests.cpp111
-rw-r--r--src/test/fuzz/addrman.cpp3
-rw-r--r--src/test/fuzz/connman.cpp2
-rw-r--r--src/test/fuzz/data_stream.cpp2
-rw-r--r--src/test/fuzz/deserialize.cpp2
-rw-r--r--src/test/net_tests.cpp20
-rw-r--r--src/test/util/setup_common.cpp2
-rwxr-xr-xtest/functional/p2p_addr_relay.py22
14 files changed, 137 insertions, 126 deletions
diff --git a/src/addrman.cpp b/src/addrman.cpp
index 96139182d3..e8f98f727b 100644
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -431,11 +431,16 @@ CAddrInfo CAddrMan::Select_(bool newOnly) const
}
}
-#ifdef DEBUG_ADDRMAN
-int CAddrMan::Check_()
+int CAddrMan::Check_() const
{
AssertLockHeld(cs);
+ // Run consistency checks 1 in m_consistency_check_ratio times if enabled
+ if (m_consistency_check_ratio == 0) return 0;
+ if (insecure_rand.randrange(m_consistency_check_ratio) >= 1) return 0;
+
+ LogPrint(BCLog::ADDRMAN, "Addrman checks started: new %i, tried %i, total %u\n", nNew, nTried, vRandom.size());
+
std::unordered_set<int> setTried;
std::unordered_map<int, int> mapNew;
@@ -458,8 +463,10 @@ int CAddrMan::Check_()
return -4;
mapNew[n] = info.nRefCount;
}
- if (mapAddr[info] != n)
+ const auto it{mapAddr.find(info)};
+ if (it == mapAddr.end() || it->second != n) {
return -5;
+ }
if (info.nRandomPos < 0 || (size_t)info.nRandomPos >= vRandom.size() || vRandom[info.nRandomPos] != n)
return -14;
if (info.nLastTry < 0)
@@ -478,10 +485,13 @@ int CAddrMan::Check_()
if (vvTried[n][i] != -1) {
if (!setTried.count(vvTried[n][i]))
return -11;
- if (mapInfo[vvTried[n][i]].GetTriedBucket(nKey, m_asmap) != n)
+ const auto it{mapInfo.find(vvTried[n][i])};
+ if (it == mapInfo.end() || it->second.GetTriedBucket(nKey, m_asmap) != n) {
return -17;
- if (mapInfo[vvTried[n][i]].GetBucketPosition(nKey, false, n) != i)
+ }
+ if (it->second.GetBucketPosition(nKey, false, n) != i) {
return -18;
+ }
setTried.erase(vvTried[n][i]);
}
}
@@ -492,8 +502,10 @@ int CAddrMan::Check_()
if (vvNew[n][i] != -1) {
if (!mapNew.count(vvNew[n][i]))
return -12;
- if (mapInfo[vvNew[n][i]].GetBucketPosition(nKey, true, n) != i)
+ const auto it{mapInfo.find(vvNew[n][i])};
+ if (it == mapInfo.end() || it->second.GetBucketPosition(nKey, true, n) != i) {
return -19;
+ }
if (--mapNew[vvNew[n][i]] == 0)
mapNew.erase(vvNew[n][i]);
}
@@ -507,9 +519,9 @@ int CAddrMan::Check_()
if (nKey.IsNull())
return -16;
+ LogPrint(BCLog::ADDRMAN, "Addrman checks completed successfully\n");
return 0;
}
-#endif
void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr, size_t max_addresses, size_t max_pct, std::optional<Network> network) const
{
diff --git a/src/addrman.h b/src/addrman.h
index 1dd1932421..3ee8c3ee09 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -26,6 +26,9 @@
#include <unordered_map>
#include <vector>
+/** Default for -checkaddrman */
+static constexpr int32_t DEFAULT_ADDRMAN_CONSISTENCY_CHECKS{0};
+
/**
* Extended statistics about a CAddress
*/
@@ -124,8 +127,8 @@ public:
* attempt was unsuccessful.
* * Bucket selection is based on cryptographic hashing, using a randomly-generated 256-bit key, which should not
* be observable by adversaries.
- * * Several indexes are kept for high performance. Defining DEBUG_ADDRMAN will introduce frequent (and expensive)
- * consistency checks for the entire data structure.
+ * * Several indexes are kept for high performance. Setting m_consistency_check_ratio with the -checkaddrman
+ * configuration option will introduce (expensive) consistency checks for the entire data structure.
*/
//! total number of buckets for tried addresses
@@ -493,9 +496,12 @@ public:
mapAddr.clear();
}
- CAddrMan()
+ explicit CAddrMan(bool deterministic, int32_t consistency_check_ratio)
+ : insecure_rand{deterministic},
+ m_consistency_check_ratio{consistency_check_ratio}
{
Clear();
+ if (deterministic) nKey = uint256{1};
}
~CAddrMan()
@@ -637,13 +643,13 @@ protected:
//! secret key to randomize bucket select with
uint256 nKey;
- //! Source of random numbers for randomization in inner loops
- mutable FastRandomContext insecure_rand GUARDED_BY(cs);
-
//! A mutex to protect the inner data structures.
mutable Mutex cs;
private:
+ //! Source of random numbers for randomization in inner loops
+ mutable FastRandomContext insecure_rand GUARDED_BY(cs);
+
//! Serialization versions.
enum Format : uint8_t {
V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
@@ -698,6 +704,9 @@ private:
//! 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;
+
//! Find an entry.
CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
@@ -735,22 +744,19 @@ private:
CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
//! Consistency check
- void Check() const
- EXCLUSIVE_LOCKS_REQUIRED(cs)
+ void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs)
{
-#ifdef DEBUG_ADDRMAN
AssertLockHeld(cs);
+
const int err = Check_();
if (err) {
LogPrintf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
+ assert(false);
}
-#endif
}
-#ifdef DEBUG_ADDRMAN
//! Perform consistency check. Returns an error code or zero.
int Check_() const EXCLUSIVE_LOCKS_REQUIRED(cs);
-#endif
/**
* Return all or many randomly selected addresses, optionally by network.
diff --git a/src/bench/addrman.cpp b/src/bench/addrman.cpp
index b7bd8a3261..5ae2dafd5a 100644
--- a/src/bench/addrman.cpp
+++ b/src/bench/addrman.cpp
@@ -72,7 +72,7 @@ static void AddrManAdd(benchmark::Bench& bench)
{
CreateAddresses();
- CAddrMan addrman;
+ CAddrMan addrman(/* deterministic */ false, /* consistency_check_ratio */ 0);
bench.run([&] {
AddAddressesToAddrMan(addrman);
@@ -82,7 +82,7 @@ static void AddrManAdd(benchmark::Bench& bench)
static void AddrManSelect(benchmark::Bench& bench)
{
- CAddrMan addrman;
+ CAddrMan addrman(/* deterministic */ false, /* consistency_check_ratio */ 0);
FillAddrMan(addrman);
@@ -94,7 +94,7 @@ static void AddrManSelect(benchmark::Bench& bench)
static void AddrManGetAddr(benchmark::Bench& bench)
{
- CAddrMan addrman;
+ CAddrMan addrman(/* deterministic */ false, /* consistency_check_ratio */ 0);
FillAddrMan(addrman);
@@ -112,10 +112,12 @@ static void AddrManGood(benchmark::Bench& bench)
* we want to do the same amount of work in every loop iteration. */
bench.epochs(5).epochIterations(1);
+ const size_t addrman_count{bench.epochs() * bench.epochIterations()};
- std::vector<CAddrMan> addrmans(bench.epochs() * bench.epochIterations());
- for (auto& addrman : addrmans) {
- FillAddrMan(addrman);
+ std::vector<std::unique_ptr<CAddrMan>> addrmans(addrman_count);
+ for (size_t i{0}; i < addrman_count; ++i) {
+ addrmans[i] = std::make_unique<CAddrMan>(/* deterministic */ false, /* consistency_check_ratio */ 0);
+ FillAddrMan(*addrmans[i]);
}
auto markSomeAsGood = [](CAddrMan& addrman) {
@@ -130,7 +132,7 @@ static void AddrManGood(benchmark::Bench& bench)
uint64_t i = 0;
bench.run([&] {
- markSomeAsGood(addrmans.at(i));
+ markSomeAsGood(*addrmans.at(i));
++i;
});
}
diff --git a/src/init.cpp b/src/init.cpp
index 1b406bed28..9154fc0a6f 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -501,7 +501,8 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-checkblocks=<n>", strprintf("How many blocks to check at startup (default: %u, 0 = all)", DEFAULT_CHECKBLOCKS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-checklevel=<n>", strprintf("How thorough the block verification of -checkblocks is: %s (0-4, default: %u)", Join(CHECKLEVEL_DOC, ", "), DEFAULT_CHECKLEVEL), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-checkblockindex", strprintf("Do a consistency check for the block tree, chainstate, and other validation data structures occasionally. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
- argsman.AddArg("-checkmempool=<n>", strprintf("Run checks every <n> transactions (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-checkaddrman=<n>", strprintf("Run addrman consistency checks every <n> operations. Use 0 to disable. (default: %u)", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
+ argsman.AddArg("-checkmempool=<n>", strprintf("Run mempool consistency checks every <n> transactions. Use 0 to disable. (default: %u, regtest: %u)", defaultChainParams->DefaultConsistencyChecks(), regtestChainParams->DefaultConsistencyChecks()), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-checkpoints", strprintf("Enable rejection of any forks from the known historical chain until block %s (default: %u)", defaultChainParams->Checkpoints().GetHeight(), DEFAULT_CHECKPOINTS_ENABLED), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-deprecatedrpc=<method>", "Allows deprecated RPC method(s) to be used", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
argsman.AddArg("-stopafterblockimport", strprintf("Stop running after importing blocks from disk (default: %u)", DEFAULT_STOPAFTERBLOCKIMPORT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::DEBUG_TEST);
@@ -1164,7 +1165,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
const bool ignores_incoming_txs{args.GetBoolArg("-blocksonly", DEFAULT_BLOCKSONLY)};
assert(!node.addrman);
- node.addrman = std::make_unique<CAddrMan>();
+ auto check_addrman = std::clamp<int32_t>(args.GetArg("-checkaddrman", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, 1000000);
+ node.addrman = std::make_unique<CAddrMan>(/* deterministic */ false, /* consistency_check_ratio */ check_addrman);
assert(!node.banman);
node.banman = std::make_unique<BanMan>(gArgs.GetDataDirNet() / "banlist", &uiInterface, args.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
assert(!node.connman);
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
index 8243ef0f55..0cb13f9253 100644
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -161,7 +161,7 @@ static constexpr size_t MAX_ADDR_TO_SEND{1000};
static constexpr double MAX_ADDR_RATE_PER_SECOND{0.1};
/** The soft limit of the address processing token bucket (the regular MAX_ADDR_RATE_PER_SECOND
* based increments won't go above this, but the MAX_ADDR_TO_SEND increment following GETADDR
- * is exempt from this limit. */
+ * is exempt from this limit). */
static constexpr size_t MAX_ADDR_PROCESSING_TOKEN_BUCKET{MAX_ADDR_TO_SEND};
// Internal stuff
@@ -263,14 +263,14 @@ struct Peer {
std::atomic_bool m_wants_addrv2{false};
/** Whether this peer has already sent us a getaddr message. */
bool m_getaddr_recvd{false};
- /** Number of addr messages that can be processed from this peer. Start at 1 to
+ /** Number of addresses that can be processed from this peer. Start at 1 to
* permit self-announcement. */
double m_addr_token_bucket{1.0};
/** When m_addr_token_bucket was last updated */
std::chrono::microseconds m_addr_token_timestamp{GetTime<std::chrono::microseconds>()};
/** Total number of addresses that were dropped due to rate limiting. */
std::atomic<uint64_t> m_addr_rate_limited{0};
- /** Total number of addresses that were processed (excludes rate limited ones). */
+ /** Total number of addresses that were processed (excludes rate-limited ones). */
std::atomic<uint64_t> m_addr_processed{0};
/** Set of txids to reconsider once their parent transactions have been accepted **/
@@ -2848,11 +2848,12 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
return;
// Apply rate limiting.
- if (rate_limited) {
- if (peer->m_addr_token_bucket < 1.0) {
+ if (peer->m_addr_token_bucket < 1.0) {
+ if (rate_limited) {
++num_rate_limit;
continue;
}
+ } else {
peer->m_addr_token_bucket -= 1.0;
}
// We only bother storing full nodes, though this may include
@@ -2880,12 +2881,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
}
peer->m_addr_processed += num_proc;
peer->m_addr_rate_limited += num_rate_limit;
- LogPrint(BCLog::NET, "Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d%s\n",
- vAddr.size(),
- num_proc,
- num_rate_limit,
- pfrom.GetId(),
- fLogIPs ? ", peeraddr=" + pfrom.addr.ToString() : "");
+ LogPrint(BCLog::NET, "Received addr: %u addresses (%u processed, %u rate-limited) from peer=%d\n",
+ vAddr.size(), num_proc, num_rate_limit, pfrom.GetId());
m_addrman.Add(vAddrOk, pfrom.addr, 2 * 60 * 60);
if (vAddr.size() < 1000) peer->m_getaddr_sent = false;
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
index abc9ec3ce3..4d066b8957 100644
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -151,6 +151,8 @@ static RPCHelpMan getpeerinfo()
{RPCResult::Type::NUM, "n", "The heights of blocks we're currently asking from this peer"},
}},
{RPCResult::Type::BOOL, "addr_relay_enabled", "Whether we participate in address relay with this peer"},
+ {RPCResult::Type::NUM, "addr_processed", "The total number of addresses processed, excluding those dropped due to rate limiting"},
+ {RPCResult::Type::NUM, "addr_rate_limited", "The total number of addresses dropped due to rate limiting"},
{RPCResult::Type::ARR, "permissions", "Any special permissions that have been granted to this peer",
{
{RPCResult::Type::STR, "permission_type", Join(NET_PERMISSIONS_DOC, ",\n") + ".\n"},
diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp
index 79c7102c4f..3c64461605 100644
--- a/src/test/addrman_tests.cpp
+++ b/src/test/addrman_tests.cpp
@@ -21,24 +21,13 @@ private:
bool deterministic;
public:
explicit CAddrManTest(bool makeDeterministic = true,
- std::vector<bool> asmap = std::vector<bool>())
+ std::vector<bool> asmap = std::vector<bool>())
+ : CAddrMan(makeDeterministic, /* consistency_check_ratio */ 100)
{
- if (makeDeterministic) {
- // Set addrman addr placement to be deterministic.
- MakeDeterministic();
- }
deterministic = makeDeterministic;
m_asmap = asmap;
}
- //! Ensure that bucket placement is always the same for testing purposes.
- void MakeDeterministic()
- {
- LOCK(cs);
- nKey.SetNull();
- insecure_rand = FastRandomContext(true);
- }
-
CAddrInfo* Find(const CNetAddr& addr, int* pnId = nullptr)
{
LOCK(cs);
@@ -89,7 +78,7 @@ public:
CAddrMan::Clear();
if (deterministic) {
LOCK(cs);
- nKey.SetNull();
+ nKey = uint256{1};
insecure_rand = FastRandomContext(true);
}
}
@@ -267,24 +256,27 @@ BOOST_AUTO_TEST_CASE(addrman_new_collisions)
CNetAddr source = ResolveIP("252.2.2.2");
- BOOST_CHECK_EQUAL(addrman.size(), 0U);
+ uint32_t num_addrs{0};
+
+ BOOST_CHECK_EQUAL(addrman.size(), num_addrs);
- for (unsigned int i = 1; i < 18; i++) {
- CService addr = ResolveService("250.1.1." + ToString(i));
+ 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(), i);
+ BOOST_CHECK_EQUAL(addrman.size(), num_addrs);
}
//Test: new table collision!
- CService addr1 = ResolveService("250.1.1.18");
+ 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(), 17U);
+ BOOST_CHECK_EQUAL(addrman.size(), num_addrs - collisions);
- CService addr2 = ResolveService("250.1.1.19");
+ CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source));
- BOOST_CHECK_EQUAL(addrman.size(), 18U);
+ BOOST_CHECK_EQUAL(addrman.size(), num_addrs - collisions);
}
BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
@@ -293,25 +285,28 @@ BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
CNetAddr source = ResolveIP("252.2.2.2");
- BOOST_CHECK_EQUAL(addrman.size(), 0U);
+ uint32_t num_addrs{0};
+
+ BOOST_CHECK_EQUAL(addrman.size(), num_addrs);
- for (unsigned int i = 1; i < 80; i++) {
- CService addr = ResolveService("250.1.1." + ToString(i));
+ while (num_addrs < 64) { // Magic number! 250.1.1.1 - 250.1.1.64 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));
addrman.Good(CAddress(addr, NODE_NONE));
//Test: No collision in tried table yet.
- BOOST_CHECK_EQUAL(addrman.size(), i);
+ BOOST_CHECK_EQUAL(addrman.size(), num_addrs);
}
//Test: tried table collision!
- CService addr1 = ResolveService("250.1.1.80");
+ 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(), 79U);
+ BOOST_CHECK_EQUAL(addrman.size(), num_addrs - collisions);
- CService addr2 = ResolveService("250.1.1.81");
+ CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
BOOST_CHECK(addrman.Add(CAddress(addr2, NODE_NONE), source));
- BOOST_CHECK_EQUAL(addrman.size(), 80U);
+ BOOST_CHECK_EQUAL(addrman.size(), num_addrs - collisions);
}
BOOST_AUTO_TEST_CASE(addrman_find)
@@ -861,9 +856,9 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
{
CAddrManTest addrman;
- // Add twenty two addresses.
+ // Add 35 addresses.
CNetAddr source = ResolveIP("252.2.2.2");
- for (unsigned int i = 1; i < 23; i++) {
+ for (unsigned int i = 1; i < 36; i++) {
CService addr = ResolveService("250.1.1."+ToString(i));
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
@@ -873,20 +868,20 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
}
- // Collision between 23 and 19.
- CService addr23 = ResolveService("250.1.1.23");
- BOOST_CHECK(addrman.Add(CAddress(addr23, NODE_NONE), source));
- addrman.Good(addr23);
+ // Collision between 36 and 19.
+ CService addr36 = ResolveService("250.1.1.36");
+ BOOST_CHECK(addrman.Add(CAddress(addr36, NODE_NONE), source));
+ addrman.Good(addr36);
- BOOST_CHECK(addrman.size() == 23);
- BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.19:0");
+ BOOST_CHECK(addrman.size() == 36);
+ BOOST_CHECK_EQUAL(addrman.SelectTriedCollision().ToString(), "250.1.1.19:0");
- // 23 should be discarded and 19 not evicted.
+ // 36 should be discarded and 19 not evicted.
addrman.ResolveCollisions();
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
// Lets create two collisions.
- for (unsigned int i = 24; i < 33; i++) {
+ for (unsigned int i = 37; i < 59; i++) {
CService addr = ResolveService("250.1.1."+ToString(i));
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
@@ -896,17 +891,17 @@ BOOST_AUTO_TEST_CASE(addrman_noevict)
}
// Cause a collision.
- CService addr33 = ResolveService("250.1.1.33");
- BOOST_CHECK(addrman.Add(CAddress(addr33, NODE_NONE), source));
- addrman.Good(addr33);
- BOOST_CHECK(addrman.size() == 33);
+ CService addr59 = ResolveService("250.1.1.59");
+ BOOST_CHECK(addrman.Add(CAddress(addr59, NODE_NONE), source));
+ addrman.Good(addr59);
+ BOOST_CHECK(addrman.size() == 59);
- BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.27:0");
+ BOOST_CHECK_EQUAL(addrman.SelectTriedCollision().ToString(), "250.1.1.10:0");
// Cause a second collision.
- BOOST_CHECK(!addrman.Add(CAddress(addr23, NODE_NONE), source));
- addrman.Good(addr23);
- BOOST_CHECK(addrman.size() == 33);
+ BOOST_CHECK(!addrman.Add(CAddress(addr36, NODE_NONE), source));
+ addrman.Good(addr36);
+ BOOST_CHECK(addrman.size() == 59);
BOOST_CHECK(addrman.SelectTriedCollision().ToString() != "[::]:0");
addrman.ResolveCollisions();
@@ -922,9 +917,9 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
// Empty addrman should return blank addrman info.
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
- // Add twenty two addresses.
+ // Add 35 addresses
CNetAddr source = ResolveIP("252.2.2.2");
- for (unsigned int i = 1; i < 23; i++) {
+ for (unsigned int i = 1; i < 36; i++) {
CService addr = ResolveService("250.1.1."+ToString(i));
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
@@ -934,34 +929,34 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
}
- // Collision between 23 and 19.
- CService addr = ResolveService("250.1.1.23");
+ // Collision between 36 and 19.
+ CService addr = ResolveService("250.1.1.36");
BOOST_CHECK(addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
- BOOST_CHECK(addrman.size() == 23);
+ BOOST_CHECK_EQUAL(addrman.size(), 36);
CAddrInfo info = addrman.SelectTriedCollision();
- BOOST_CHECK(info.ToString() == "250.1.1.19:0");
+ BOOST_CHECK_EQUAL(info.ToString(), "250.1.1.19:0");
// Ensure test of address fails, so that it is evicted.
addrman.SimConnFail(info);
- // Should swap 23 for 19.
+ // Should swap 36 for 19.
addrman.ResolveCollisions();
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
- // If 23 was swapped for 19, then this should cause no collisions.
+ // If 36 was swapped for 19, then this should cause no collisions.
BOOST_CHECK(!addrman.Add(CAddress(addr, NODE_NONE), source));
addrman.Good(addr);
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
- // If we insert 19 is should collide with 23.
+ // If we insert 19 it should collide with 36
CService addr19 = ResolveService("250.1.1.19");
BOOST_CHECK(!addrman.Add(CAddress(addr19, NODE_NONE), source));
addrman.Good(addr19);
- BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "250.1.1.23:0");
+ BOOST_CHECK_EQUAL(addrman.SelectTriedCollision().ToString(), "250.1.1.36:0");
addrman.ResolveCollisions();
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
diff --git a/src/test/fuzz/addrman.cpp b/src/test/fuzz/addrman.cpp
index 4c29a8ee53..60fba5730a 100644
--- a/src/test/fuzz/addrman.cpp
+++ b/src/test/fuzz/addrman.cpp
@@ -29,7 +29,8 @@ public:
FuzzedDataProvider& m_fuzzed_data_provider;
explicit CAddrManDeterministic(FuzzedDataProvider& fuzzed_data_provider)
- : m_fuzzed_data_provider(fuzzed_data_provider)
+ : CAddrMan(/* deterministic */ true, /* consistency_check_ratio */ 0)
+ , m_fuzzed_data_provider(fuzzed_data_provider)
{
WITH_LOCK(cs, insecure_rand = FastRandomContext{ConsumeUInt256(fuzzed_data_provider)});
if (fuzzed_data_provider.ConsumeBool()) {
diff --git a/src/test/fuzz/connman.cpp b/src/test/fuzz/connman.cpp
index bbec5943af..0e323ddc20 100644
--- a/src/test/fuzz/connman.cpp
+++ b/src/test/fuzz/connman.cpp
@@ -25,7 +25,7 @@ FUZZ_TARGET_INIT(connman, initialize_connman)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
SetMockTime(ConsumeTime(fuzzed_data_provider));
- CAddrMan addrman;
+ CAddrMan addrman(/* deterministic */ false, /* consistency_check_ratio */ 0);
CConnman connman{fuzzed_data_provider.ConsumeIntegral<uint64_t>(), fuzzed_data_provider.ConsumeIntegral<uint64_t>(), addrman, fuzzed_data_provider.ConsumeBool()};
CNetAddr random_netaddr;
CNode random_node = ConsumeNode(fuzzed_data_provider);
diff --git a/src/test/fuzz/data_stream.cpp b/src/test/fuzz/data_stream.cpp
index 473caec6ff..53400082ab 100644
--- a/src/test/fuzz/data_stream.cpp
+++ b/src/test/fuzz/data_stream.cpp
@@ -21,6 +21,6 @@ FUZZ_TARGET_INIT(data_stream_addr_man, initialize_data_stream_addr_man)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
CDataStream data_stream = ConsumeDataStream(fuzzed_data_provider);
- CAddrMan addr_man;
+ CAddrMan addr_man(/* deterministic */ false, /* consistency_check_ratio */ 0);
CAddrDB::Read(addr_man, data_stream);
}
diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp
index d5b56cb7cd..49503e8dc6 100644
--- a/src/test/fuzz/deserialize.cpp
+++ b/src/test/fuzz/deserialize.cpp
@@ -188,7 +188,7 @@ FUZZ_TARGET_DESERIALIZE(blockmerkleroot, {
BlockMerkleRoot(block, &mutated);
})
FUZZ_TARGET_DESERIALIZE(addrman_deserialize, {
- CAddrMan am;
+ CAddrMan am(/* deterministic */ false, /* consistency_check_ratio */ 0);
DeserializeFromFuzzingInput(buffer, am);
})
FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, {
diff --git a/src/test/net_tests.cpp b/src/test/net_tests.cpp
index acbbf357d2..1915f9c7d5 100644
--- a/src/test/net_tests.cpp
+++ b/src/test/net_tests.cpp
@@ -34,13 +34,9 @@ class CAddrManSerializationMock : public CAddrMan
public:
virtual void Serialize(CDataStream& s) const = 0;
- //! Ensure that bucket placement is always the same for testing purposes.
- void MakeDeterministic()
- {
- LOCK(cs);
- nKey.SetNull();
- insecure_rand = FastRandomContext(true);
- }
+ CAddrManSerializationMock()
+ : CAddrMan(/* deterministic */ true, /* consistency_check_ratio */ 100)
+ {}
};
class CAddrManUncorrupted : public CAddrManSerializationMock
@@ -105,7 +101,6 @@ BOOST_AUTO_TEST_CASE(cnode_listen_port)
BOOST_AUTO_TEST_CASE(caddrdb_read)
{
CAddrManUncorrupted addrmanUncorrupted;
- addrmanUncorrupted.MakeDeterministic();
CService addr1, addr2, addr3;
BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false));
@@ -124,7 +119,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
// Test that the de-serialization does not throw an exception.
CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted);
bool exceptionThrown = false;
- CAddrMan addrman1;
+ CAddrMan addrman1(/* deterministic */ false, /* consistency_check_ratio */ 100);
BOOST_CHECK(addrman1.size() == 0);
try {
@@ -141,7 +136,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
// Test that CAddrDB::Read creates an addrman with the correct number of addrs.
CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted);
- CAddrMan addrman2;
+ CAddrMan addrman2(/* deterministic */ false, /* consistency_check_ratio */ 100);
BOOST_CHECK(addrman2.size() == 0);
BOOST_CHECK(CAddrDB::Read(addrman2, ssPeers2));
BOOST_CHECK(addrman2.size() == 3);
@@ -151,12 +146,11 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
{
CAddrManCorrupted addrmanCorrupted;
- addrmanCorrupted.MakeDeterministic();
// Test that the de-serialization of corrupted addrman throws an exception.
CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted);
bool exceptionThrown = false;
- CAddrMan addrman1;
+ CAddrMan addrman1(/* deterministic */ false, /* consistency_check_ratio */ 100);
BOOST_CHECK(addrman1.size() == 0);
try {
unsigned char pchMsgTmp[4];
@@ -172,7 +166,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
// Test that CAddrDB::Read leaves addrman in a clean state if de-serialization fails.
CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted);
- CAddrMan addrman2;
+ CAddrMan addrman2(/* deterministic */ false, /* consistency_check_ratio */ 100);
BOOST_CHECK(addrman2.size() == 0);
BOOST_CHECK(!CAddrDB::Read(addrman2, ssPeers2));
BOOST_CHECK(addrman2.size() == 0);
diff --git a/src/test/util/setup_common.cpp b/src/test/util/setup_common.cpp
index ce81fc378f..c9bb863a7b 100644
--- a/src/test/util/setup_common.cpp
+++ b/src/test/util/setup_common.cpp
@@ -193,7 +193,7 @@ TestingSetup::TestingSetup(const std::string& chainName, const std::vector<const
throw std::runtime_error(strprintf("ActivateBestChain failed. (%s)", state.ToString()));
}
- m_node.addrman = std::make_unique<CAddrMan>();
+ m_node.addrman = std::make_unique<CAddrMan>(/* deterministic */ false, /* consistency_check_ratio */ 0);
m_node.banman = std::make_unique<BanMan>(m_args.GetDataDirBase() / "banlist", nullptr, DEFAULT_MISBEHAVING_BANTIME);
m_node.connman = std::make_unique<CConnman>(0x1337, 0x1337, *m_node.addrman); // Deterministic randomness for tests.
m_node.peerman = PeerManager::make(chainparams, *m_node.connman, *m_node.addrman,
diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py
index 113e1f9492..e93698b08e 100755
--- a/test/functional/p2p_addr_relay.py
+++ b/test/functional/p2p_addr_relay.py
@@ -311,7 +311,7 @@ class AddrTest(BitcoinTestFramework):
self.nodes[0].disconnect_p2ps()
- def send_addrs_and_test_rate_limiting(self, peer, no_relay, new_addrs, total_addrs):
+ def send_addrs_and_test_rate_limiting(self, peer, no_relay, *, new_addrs, total_addrs):
"""Send an addr message and check that the number of addresses processed and rate-limited is as expected"""
peer.send_and_ping(self.setup_rand_addr_msg(new_addrs))
@@ -329,27 +329,26 @@ class AddrTest(BitcoinTestFramework):
assert_equal(addrs_rate_limited, max(0, total_addrs - peer.tokens))
def rate_limit_tests(self):
-
self.mocktime = int(time.time())
self.restart_node(0, [])
self.nodes[0].setmocktime(self.mocktime)
- for contype, no_relay in [("outbound-full-relay", False), ("block-relay-only", True), ("inbound", False)]:
- self.log.info(f'Test rate limiting of addr processing for {contype} peers')
- if contype == "inbound":
+ for conn_type, no_relay in [("outbound-full-relay", False), ("block-relay-only", True), ("inbound", False)]:
+ self.log.info(f'Test rate limiting of addr processing for {conn_type} peers')
+ if conn_type == "inbound":
peer = self.nodes[0].add_p2p_connection(AddrReceiver())
else:
- peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type=contype)
+ peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type=conn_type)
# Send 600 addresses. For all but the block-relay-only peer this should result in addresses being processed.
- self.send_addrs_and_test_rate_limiting(peer, no_relay, 600, 600)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=600, total_addrs=600)
# Send 600 more addresses. For the outbound-full-relay peer (which we send a GETADDR, and thus will
# process up to 1001 incoming addresses), this means more addresses will be processed.
- self.send_addrs_and_test_rate_limiting(peer, no_relay, 600, 1200)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=600, total_addrs=1200)
# Send 10 more. As we reached the processing limit for all nodes, no more addresses should be procesesd.
- self.send_addrs_and_test_rate_limiting(peer, no_relay, 10, 1210)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=10, total_addrs=1210)
# Advance the time by 100 seconds, permitting the processing of 10 more addresses.
# Send 200 and verify that 10 are processed.
@@ -357,7 +356,7 @@ class AddrTest(BitcoinTestFramework):
self.nodes[0].setmocktime(self.mocktime)
peer.increment_tokens(10)
- self.send_addrs_and_test_rate_limiting(peer, no_relay, 200, 1410)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=200, total_addrs=1410)
# Advance the time by 1000 seconds, permitting the processing of 100 more addresses.
# Send 200 and verify that 100 are processed.
@@ -365,9 +364,10 @@ class AddrTest(BitcoinTestFramework):
self.nodes[0].setmocktime(self.mocktime)
peer.increment_tokens(100)
- self.send_addrs_and_test_rate_limiting(peer, no_relay, 200, 1610)
+ self.send_addrs_and_test_rate_limiting(peer, no_relay, new_addrs=200, total_addrs=1610)
self.nodes[0].disconnect_p2ps()
+
if __name__ == '__main__':
AddrTest().main()