mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-05 14:06:27 -05:00
Merge bitcoin/bitcoin#22697: addrman: Remove CAddrMan::Clear() function
4d2fa97031
[addrman] Clean up ctor (John Newbery)7e6e65918f
[addrman] inline Clear() into CAddrMan ctor (John Newbery)406be5ff96
[addrman] Remove all public uses of CAddrMan.Clear() from the tests (John Newbery)ed9ba8af08
[tests] Remove CAddrMan.Clear() call from CAddrDB::Read() (John Newbery)e8e7392311
[addrman] Don't call Clear() if parsing peers.dat fails (John Newbery)181a1207ba
[addrman] Move peers.dat parsing to init.cpp (John Newbery) Pull request description: `CAddrMan::Clear()` exists to reset the internal state of `CAddrMan`. It's currently used in two places: - on startup, if deserializing peers.dat fails, `Clear()` is called to reset to an empty addrman - in tests, `Clear()` is called to reset the addrman for more tests In both cases, we can simply destruct the `CAddrMan` and construct a new, empty addrman. That approach is safer - it's possible that `Clear()` could 'reset' the addrman to a state that's not equivalent to a freshly constructed addrman (one actual example of this is that `Clear()` does not clear the `m_tried_collisions` set). On the other hand, if we destruct and then construct a fresh addrman, we're guaranteed that the new object is empty. This wasn't possible when addrman was initially implemented, since it was a global, and so it would only be destructed on shutdown. However, addrman is now owned by `node.context`, so we have control over its destruction/construction. ACKs for top commit: laanwj: Code review ACK4d2fa97031
vasild: ACK4d2fa97031
Zero-1729: crACK4d2fa97031
Tree-SHA512: f715bf2cbff4f8c3a9dbc613f8c7f11846b065d6807faf3c7d346a0b0b29cbe7ce1dc0509465c2c9b88a8ad55299c9182ea53f5f743e47502a69a0f375e09408
This commit is contained in:
commit
602c8eb8f0
8 changed files with 98 additions and 140 deletions
|
@ -244,12 +244,7 @@ bool CAddrDB::Read(CAddrMan& addr)
|
||||||
|
|
||||||
bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
|
bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
|
||||||
{
|
{
|
||||||
bool ret = DeserializeDB(ssPeers, addr, false);
|
return DeserializeDB(ssPeers, addr, false);
|
||||||
if (!ret) {
|
|
||||||
// Ensure addrman is left in a clean state
|
|
||||||
addr.Clear();
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpAnchors(const fs::path& anchors_db_path, const std::vector<CAddress>& anchors)
|
void DumpAnchors(const fs::path& anchors_db_path, const std::vector<CAddress>& anchors)
|
||||||
|
|
|
@ -77,6 +77,23 @@ double CAddrInfo::GetChance(int64_t nNow) const
|
||||||
return fChance;
|
return fChance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CAddrMan::CAddrMan(bool deterministic, int32_t consistency_check_ratio)
|
||||||
|
: insecure_rand{deterministic}
|
||||||
|
, nKey{deterministic ? uint256{1} : insecure_rand.rand256()}
|
||||||
|
, m_consistency_check_ratio{consistency_check_ratio}
|
||||||
|
{
|
||||||
|
for (auto& bucket : vvNew) {
|
||||||
|
for (auto& entry : bucket) {
|
||||||
|
entry = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto& bucket : vvTried) {
|
||||||
|
for (auto& entry : bucket) {
|
||||||
|
entry = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
|
CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
|
||||||
{
|
{
|
||||||
AssertLockHeld(cs);
|
AssertLockHeld(cs);
|
||||||
|
|
|
@ -471,38 +471,7 @@ public:
|
||||||
Check();
|
Check();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear()
|
explicit CAddrMan(bool deterministic, int32_t consistency_check_ratio);
|
||||||
EXCLUSIVE_LOCKS_REQUIRED(!cs)
|
|
||||||
{
|
|
||||||
LOCK(cs);
|
|
||||||
std::vector<int>().swap(vRandom);
|
|
||||||
nKey = insecure_rand.rand256();
|
|
||||||
for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
|
|
||||||
for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
|
|
||||||
vvNew[bucket][entry] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; bucket++) {
|
|
||||||
for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
|
|
||||||
vvTried[bucket][entry] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nIdCount = 0;
|
|
||||||
nTried = 0;
|
|
||||||
nNew = 0;
|
|
||||||
nLastGood = 1; //Initially at 1 so that "never" is strictly worse.
|
|
||||||
mapInfo.clear();
|
|
||||||
mapAddr.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
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()
|
~CAddrMan()
|
||||||
{
|
{
|
||||||
|
@ -624,17 +593,16 @@ public:
|
||||||
Check();
|
Check();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
//! secret key to randomize bucket select with
|
|
||||||
uint256 nKey;
|
|
||||||
|
|
||||||
//! A mutex to protect the inner data structures.
|
//! A mutex to protect the inner data structures.
|
||||||
mutable Mutex cs;
|
mutable Mutex cs;
|
||||||
|
|
||||||
private:
|
|
||||||
//! Source of random numbers for randomization in inner loops
|
//! Source of random numbers for randomization in inner loops
|
||||||
mutable FastRandomContext insecure_rand GUARDED_BY(cs);
|
mutable FastRandomContext insecure_rand GUARDED_BY(cs);
|
||||||
|
|
||||||
|
//! secret key to randomize bucket select with
|
||||||
|
uint256 nKey;
|
||||||
|
|
||||||
//! Serialization versions.
|
//! Serialization versions.
|
||||||
enum Format : uint8_t {
|
enum Format : uint8_t {
|
||||||
V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
|
V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
|
||||||
|
@ -658,7 +626,7 @@ private:
|
||||||
static constexpr uint8_t INCOMPATIBILITY_BASE = 32;
|
static constexpr uint8_t INCOMPATIBILITY_BASE = 32;
|
||||||
|
|
||||||
//! last used nId
|
//! last used nId
|
||||||
int nIdCount GUARDED_BY(cs);
|
int nIdCount GUARDED_BY(cs){0};
|
||||||
|
|
||||||
//! table with information about all nIds
|
//! table with information about all nIds
|
||||||
std::unordered_map<int, CAddrInfo> mapInfo GUARDED_BY(cs);
|
std::unordered_map<int, CAddrInfo> mapInfo GUARDED_BY(cs);
|
||||||
|
@ -672,19 +640,19 @@ private:
|
||||||
mutable std::vector<int> vRandom GUARDED_BY(cs);
|
mutable std::vector<int> vRandom GUARDED_BY(cs);
|
||||||
|
|
||||||
// number of "tried" entries
|
// number of "tried" entries
|
||||||
int nTried GUARDED_BY(cs);
|
int nTried GUARDED_BY(cs){0};
|
||||||
|
|
||||||
//! list of "tried" buckets
|
//! list of "tried" buckets
|
||||||
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
|
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
|
||||||
|
|
||||||
//! number of (unique) "new" entries
|
//! number of (unique) "new" entries
|
||||||
int nNew GUARDED_BY(cs);
|
int nNew GUARDED_BY(cs){0};
|
||||||
|
|
||||||
//! list of "new" buckets
|
//! list of "new" buckets
|
||||||
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
|
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs);
|
||||||
|
|
||||||
//! last time Good was called (memory only)
|
//! last time Good was called (memory only). Initially set to 1 so that "never" is strictly worse.
|
||||||
int64_t nLastGood GUARDED_BY(cs);
|
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.
|
//! Holds addrs inserted into tried table that collide with existing entries. Test-before-evict discipline used to resolve these collisions.
|
||||||
std::set<int> m_tried_collisions;
|
std::set<int> m_tried_collisions;
|
||||||
|
|
|
@ -72,11 +72,9 @@ static void AddrManAdd(benchmark::Bench& bench)
|
||||||
{
|
{
|
||||||
CreateAddresses();
|
CreateAddresses();
|
||||||
|
|
||||||
CAddrMan addrman(/* deterministic */ false, /* consistency_check_ratio */ 0);
|
|
||||||
|
|
||||||
bench.run([&] {
|
bench.run([&] {
|
||||||
|
CAddrMan addrman{/* deterministic */ false, /* consistency_check_ratio */ 0};
|
||||||
AddAddressesToAddrMan(addrman);
|
AddAddressesToAddrMan(addrman);
|
||||||
addrman.Clear();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/init.cpp
14
src/init.cpp
|
@ -1167,6 +1167,20 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
||||||
assert(!node.addrman);
|
assert(!node.addrman);
|
||||||
auto check_addrman = std::clamp<int32_t>(args.GetArg("-checkaddrman", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, 1000000);
|
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);
|
node.addrman = std::make_unique<CAddrMan>(/* deterministic */ false, /* consistency_check_ratio */ check_addrman);
|
||||||
|
{
|
||||||
|
// Load addresses from peers.dat
|
||||||
|
uiInterface.InitMessage(_("Loading P2P addresses…").translated);
|
||||||
|
int64_t nStart = GetTimeMillis();
|
||||||
|
CAddrDB adb;
|
||||||
|
if (adb.Read(*node.addrman)) {
|
||||||
|
LogPrintf("Loaded %i addresses from peers.dat %dms\n", node.addrman->size(), GetTimeMillis() - nStart);
|
||||||
|
} else {
|
||||||
|
// Addrman can be in an inconsistent state after failure, reset it
|
||||||
|
node.addrman = std::make_unique<CAddrMan>(/* deterministic */ false, /* consistency_check_ratio */ check_addrman);
|
||||||
|
LogPrintf("Recreating peers.dat\n");
|
||||||
|
adb.Write(*node.addrman);
|
||||||
|
}
|
||||||
|
}
|
||||||
assert(!node.banman);
|
assert(!node.banman);
|
||||||
node.banman = std::make_unique<BanMan>(gArgs.GetDataDirNet() / "banlist", &uiInterface, args.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
|
node.banman = std::make_unique<BanMan>(gArgs.GetDataDirNet() / "banlist", &uiInterface, args.GetArg("-bantime", DEFAULT_MISBEHAVING_BANTIME));
|
||||||
assert(!node.connman);
|
assert(!node.connman);
|
||||||
|
|
16
src/net.cpp
16
src/net.cpp
|
@ -2534,22 +2534,6 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
|
||||||
AddAddrFetch(strDest);
|
AddAddrFetch(strDest);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_client_interface) {
|
|
||||||
m_client_interface->InitMessage(_("Loading P2P addresses…").translated);
|
|
||||||
}
|
|
||||||
// Load addresses from peers.dat
|
|
||||||
int64_t nStart = GetTimeMillis();
|
|
||||||
{
|
|
||||||
CAddrDB adb;
|
|
||||||
if (adb.Read(addrman))
|
|
||||||
LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart);
|
|
||||||
else {
|
|
||||||
addrman.Clear(); // Addrman can be in an inconsistent state after failure, reset it
|
|
||||||
LogPrintf("Recreating peers.dat\n");
|
|
||||||
DumpAddresses();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_use_addrman_outgoing) {
|
if (m_use_addrman_outgoing) {
|
||||||
// Load addresses from anchors.dat
|
// Load addresses from anchors.dat
|
||||||
m_anchors = ReadAnchors(gArgs.GetDataDirNet() / ANCHORS_DATABASE_FILENAME);
|
m_anchors = ReadAnchors(gArgs.GetDataDirNet() / ANCHORS_DATABASE_FILENAME);
|
||||||
|
|
|
@ -48,7 +48,7 @@ public:
|
||||||
unsigned char nVersion = 1;
|
unsigned char nVersion = 1;
|
||||||
s << nVersion;
|
s << nVersion;
|
||||||
s << ((unsigned char)32);
|
s << ((unsigned char)32);
|
||||||
s << nKey;
|
s << uint256::ONE;
|
||||||
s << 10; // nNew
|
s << 10; // nNew
|
||||||
s << 10; // nTried
|
s << 10; // nTried
|
||||||
|
|
||||||
|
@ -132,16 +132,6 @@ public:
|
||||||
int64_t nLastTry = GetAdjustedTime()-61;
|
int64_t nLastTry = GetAdjustedTime()-61;
|
||||||
Attempt(addr, count_failure, nLastTry);
|
Attempt(addr, count_failure, nLastTry);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
CAddrMan::Clear();
|
|
||||||
if (deterministic) {
|
|
||||||
LOCK(cs);
|
|
||||||
nKey = uint256{1};
|
|
||||||
insecure_rand = FastRandomContext(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static CNetAddr ResolveIP(const std::string& ip)
|
static CNetAddr ResolveIP(const std::string& ip)
|
||||||
|
@ -175,27 +165,27 @@ BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(addrman_simple)
|
BOOST_AUTO_TEST_CASE(addrman_simple)
|
||||||
{
|
{
|
||||||
CAddrManTest addrman;
|
auto addrman = std::make_unique<CAddrManTest>();
|
||||||
|
|
||||||
CNetAddr source = ResolveIP("252.2.2.2");
|
CNetAddr source = ResolveIP("252.2.2.2");
|
||||||
|
|
||||||
// Test: Does Addrman respond correctly when empty.
|
// Test: Does Addrman respond correctly when empty.
|
||||||
BOOST_CHECK_EQUAL(addrman.size(), 0U);
|
BOOST_CHECK_EQUAL(addrman->size(), 0U);
|
||||||
CAddrInfo addr_null = addrman.Select();
|
CAddrInfo addr_null = addrman->Select();
|
||||||
BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
|
BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
|
||||||
|
|
||||||
// Test: Does Addrman::Add work as expected.
|
// Test: Does Addrman::Add work as expected.
|
||||||
CService addr1 = ResolveService("250.1.1.1", 8333);
|
CService addr1 = ResolveService("250.1.1.1", 8333);
|
||||||
BOOST_CHECK(addrman.Add({CAddress(addr1, NODE_NONE)}, source));
|
BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
|
||||||
BOOST_CHECK_EQUAL(addrman.size(), 1U);
|
BOOST_CHECK_EQUAL(addrman->size(), 1U);
|
||||||
CAddrInfo addr_ret1 = addrman.Select();
|
CAddrInfo addr_ret1 = addrman->Select();
|
||||||
BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
|
BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
|
||||||
|
|
||||||
// Test: Does IP address deduplication work correctly.
|
// Test: Does IP address deduplication work correctly.
|
||||||
// Expected dup IP should not be added.
|
// Expected dup IP should not be added.
|
||||||
CService addr1_dup = ResolveService("250.1.1.1", 8333);
|
CService addr1_dup = ResolveService("250.1.1.1", 8333);
|
||||||
BOOST_CHECK(!addrman.Add({CAddress(addr1_dup, NODE_NONE)}, source));
|
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
|
// Test: New table has one addr and we add a diff addr we should
|
||||||
|
@ -205,21 +195,16 @@ BOOST_AUTO_TEST_CASE(addrman_simple)
|
||||||
// success.
|
// success.
|
||||||
|
|
||||||
CService addr2 = ResolveService("250.1.1.2", 8333);
|
CService addr2 = ResolveService("250.1.1.2", 8333);
|
||||||
BOOST_CHECK(addrman.Add({CAddress(addr2, NODE_NONE)}, source));
|
BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
|
||||||
BOOST_CHECK(addrman.size() >= 1);
|
BOOST_CHECK(addrman->size() >= 1);
|
||||||
|
|
||||||
// Test: AddrMan::Clear() should empty the new table.
|
// Test: reset addrman and test AddrMan::Add multiple addresses works as expected
|
||||||
addrman.Clear();
|
addrman = std::make_unique<CAddrManTest>();
|
||||||
BOOST_CHECK_EQUAL(addrman.size(), 0U);
|
|
||||||
CAddrInfo addr_null2 = addrman.Select();
|
|
||||||
BOOST_CHECK_EQUAL(addr_null2.ToString(), "[::]:0");
|
|
||||||
|
|
||||||
// Test: AddrMan::Add multiple addresses works as expected
|
|
||||||
std::vector<CAddress> vAddr;
|
std::vector<CAddress> vAddr;
|
||||||
vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
|
vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
|
||||||
vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
|
vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
|
||||||
BOOST_CHECK(addrman.Add(vAddr, source));
|
BOOST_CHECK(addrman->Add(vAddr, source));
|
||||||
BOOST_CHECK(addrman.size() >= 1);
|
BOOST_CHECK(addrman->size() >= 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(addrman_ports)
|
BOOST_AUTO_TEST_CASE(addrman_ports)
|
||||||
|
@ -774,23 +759,23 @@ BOOST_AUTO_TEST_CASE(addrman_serialization)
|
||||||
{
|
{
|
||||||
std::vector<bool> asmap1 = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
|
std::vector<bool> asmap1 = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
|
||||||
|
|
||||||
CAddrManTest addrman_asmap1(true, asmap1);
|
auto addrman_asmap1 = std::make_unique<CAddrManTest>(true, asmap1);
|
||||||
CAddrManTest addrman_asmap1_dup(true, asmap1);
|
auto addrman_asmap1_dup = std::make_unique<CAddrManTest>(true, asmap1);
|
||||||
CAddrManTest addrman_noasmap;
|
auto addrman_noasmap = std::make_unique<CAddrManTest>();
|
||||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
|
||||||
CAddress addr = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
|
CAddress addr = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
|
||||||
CNetAddr default_source;
|
CNetAddr default_source;
|
||||||
|
|
||||||
|
|
||||||
addrman_asmap1.Add({addr}, default_source);
|
addrman_asmap1->Add({addr}, default_source);
|
||||||
|
|
||||||
stream << addrman_asmap1;
|
stream << *addrman_asmap1;
|
||||||
// serizalizing/deserializing addrman with the same asmap
|
// serizalizing/deserializing addrman with the same asmap
|
||||||
stream >> addrman_asmap1_dup;
|
stream >> *addrman_asmap1_dup;
|
||||||
|
|
||||||
std::pair<int, int> bucketAndEntry_asmap1 = addrman_asmap1.GetBucketAndEntry(addr);
|
std::pair<int, int> bucketAndEntry_asmap1 = addrman_asmap1->GetBucketAndEntry(addr);
|
||||||
std::pair<int, int> bucketAndEntry_asmap1_dup = addrman_asmap1_dup.GetBucketAndEntry(addr);
|
std::pair<int, int> bucketAndEntry_asmap1_dup = addrman_asmap1_dup->GetBucketAndEntry(addr);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1.second != -1);
|
BOOST_CHECK(bucketAndEntry_asmap1.second != -1);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1_dup.second != -1);
|
BOOST_CHECK(bucketAndEntry_asmap1_dup.second != -1);
|
||||||
|
|
||||||
|
@ -798,39 +783,39 @@ BOOST_AUTO_TEST_CASE(addrman_serialization)
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1.second == bucketAndEntry_asmap1_dup.second);
|
BOOST_CHECK(bucketAndEntry_asmap1.second == bucketAndEntry_asmap1_dup.second);
|
||||||
|
|
||||||
// deserializing asmaped peers.dat to non-asmaped addrman
|
// deserializing asmaped peers.dat to non-asmaped addrman
|
||||||
stream << addrman_asmap1;
|
stream << *addrman_asmap1;
|
||||||
stream >> addrman_noasmap;
|
stream >> *addrman_noasmap;
|
||||||
std::pair<int, int> bucketAndEntry_noasmap = addrman_noasmap.GetBucketAndEntry(addr);
|
std::pair<int, int> bucketAndEntry_noasmap = addrman_noasmap->GetBucketAndEntry(addr);
|
||||||
BOOST_CHECK(bucketAndEntry_noasmap.second != -1);
|
BOOST_CHECK(bucketAndEntry_noasmap.second != -1);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1.first != bucketAndEntry_noasmap.first);
|
BOOST_CHECK(bucketAndEntry_asmap1.first != bucketAndEntry_noasmap.first);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1.second != bucketAndEntry_noasmap.second);
|
BOOST_CHECK(bucketAndEntry_asmap1.second != bucketAndEntry_noasmap.second);
|
||||||
|
|
||||||
// deserializing non-asmaped peers.dat to asmaped addrman
|
// deserializing non-asmaped peers.dat to asmaped addrman
|
||||||
addrman_asmap1.Clear();
|
addrman_asmap1 = std::make_unique<CAddrManTest>(true, asmap1);
|
||||||
addrman_noasmap.Clear();
|
addrman_noasmap = std::make_unique<CAddrManTest>();
|
||||||
addrman_noasmap.Add({addr}, default_source);
|
addrman_noasmap->Add({addr}, default_source);
|
||||||
stream << addrman_noasmap;
|
stream << *addrman_noasmap;
|
||||||
stream >> addrman_asmap1;
|
stream >> *addrman_asmap1;
|
||||||
std::pair<int, int> bucketAndEntry_asmap1_deser = addrman_asmap1.GetBucketAndEntry(addr);
|
std::pair<int, int> bucketAndEntry_asmap1_deser = addrman_asmap1->GetBucketAndEntry(addr);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1_deser.second != -1);
|
BOOST_CHECK(bucketAndEntry_asmap1_deser.second != -1);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1_deser.first != bucketAndEntry_noasmap.first);
|
BOOST_CHECK(bucketAndEntry_asmap1_deser.first != bucketAndEntry_noasmap.first);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1_deser.first == bucketAndEntry_asmap1_dup.first);
|
BOOST_CHECK(bucketAndEntry_asmap1_deser.first == bucketAndEntry_asmap1_dup.first);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1_deser.second == bucketAndEntry_asmap1_dup.second);
|
BOOST_CHECK(bucketAndEntry_asmap1_deser.second == bucketAndEntry_asmap1_dup.second);
|
||||||
|
|
||||||
// used to map to different buckets, now maps to the same bucket.
|
// used to map to different buckets, now maps to the same bucket.
|
||||||
addrman_asmap1.Clear();
|
addrman_asmap1 = std::make_unique<CAddrManTest>(true, asmap1);
|
||||||
addrman_noasmap.Clear();
|
addrman_noasmap = std::make_unique<CAddrManTest>();
|
||||||
CAddress addr1 = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
|
CAddress addr1 = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
|
||||||
CAddress addr2 = CAddress(ResolveService("250.2.1.1"), NODE_NONE);
|
CAddress addr2 = CAddress(ResolveService("250.2.1.1"), NODE_NONE);
|
||||||
addrman_noasmap.Add({addr, addr2}, default_source);
|
addrman_noasmap->Add({addr, addr2}, default_source);
|
||||||
std::pair<int, int> bucketAndEntry_noasmap_addr1 = addrman_noasmap.GetBucketAndEntry(addr1);
|
std::pair<int, int> bucketAndEntry_noasmap_addr1 = addrman_noasmap->GetBucketAndEntry(addr1);
|
||||||
std::pair<int, int> bucketAndEntry_noasmap_addr2 = addrman_noasmap.GetBucketAndEntry(addr2);
|
std::pair<int, int> bucketAndEntry_noasmap_addr2 = addrman_noasmap->GetBucketAndEntry(addr2);
|
||||||
BOOST_CHECK(bucketAndEntry_noasmap_addr1.first != bucketAndEntry_noasmap_addr2.first);
|
BOOST_CHECK(bucketAndEntry_noasmap_addr1.first != bucketAndEntry_noasmap_addr2.first);
|
||||||
BOOST_CHECK(bucketAndEntry_noasmap_addr1.second != bucketAndEntry_noasmap_addr2.second);
|
BOOST_CHECK(bucketAndEntry_noasmap_addr1.second != bucketAndEntry_noasmap_addr2.second);
|
||||||
stream << addrman_noasmap;
|
stream << *addrman_noasmap;
|
||||||
stream >> addrman_asmap1;
|
stream >> *addrman_asmap1;
|
||||||
std::pair<int, int> bucketAndEntry_asmap1_deser_addr1 = addrman_asmap1.GetBucketAndEntry(addr1);
|
std::pair<int, int> bucketAndEntry_asmap1_deser_addr1 = addrman_asmap1->GetBucketAndEntry(addr1);
|
||||||
std::pair<int, int> bucketAndEntry_asmap1_deser_addr2 = addrman_asmap1.GetBucketAndEntry(addr2);
|
std::pair<int, int> bucketAndEntry_asmap1_deser_addr2 = addrman_asmap1->GetBucketAndEntry(addr2);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.first == bucketAndEntry_asmap1_deser_addr2.first);
|
BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.first == bucketAndEntry_asmap1_deser_addr2.first);
|
||||||
BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.second != bucketAndEntry_asmap1_deser_addr2.second);
|
BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.second != bucketAndEntry_asmap1_deser_addr2.second);
|
||||||
}
|
}
|
||||||
|
@ -839,7 +824,7 @@ BOOST_AUTO_TEST_CASE(remove_invalid)
|
||||||
{
|
{
|
||||||
// Confirm that invalid addresses are ignored in unserialization.
|
// Confirm that invalid addresses are ignored in unserialization.
|
||||||
|
|
||||||
CAddrManTest addrman;
|
auto addrman = std::make_unique<CAddrManTest>();
|
||||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
|
||||||
const CAddress new1{ResolveService("5.5.5.5"), NODE_NONE};
|
const CAddress new1{ResolveService("5.5.5.5"), NODE_NONE};
|
||||||
|
@ -847,12 +832,12 @@ BOOST_AUTO_TEST_CASE(remove_invalid)
|
||||||
const CAddress tried1{ResolveService("7.7.7.7"), NODE_NONE};
|
const CAddress tried1{ResolveService("7.7.7.7"), NODE_NONE};
|
||||||
const CAddress tried2{ResolveService("8.8.8.8"), NODE_NONE};
|
const CAddress tried2{ResolveService("8.8.8.8"), NODE_NONE};
|
||||||
|
|
||||||
addrman.Add({new1, tried1, new2, tried2}, CNetAddr{});
|
addrman->Add({new1, tried1, new2, tried2}, CNetAddr{});
|
||||||
addrman.Good(tried1);
|
addrman->Good(tried1);
|
||||||
addrman.Good(tried2);
|
addrman->Good(tried2);
|
||||||
BOOST_REQUIRE_EQUAL(addrman.size(), 4);
|
BOOST_REQUIRE_EQUAL(addrman->size(), 4);
|
||||||
|
|
||||||
stream << addrman;
|
stream << *addrman;
|
||||||
|
|
||||||
const std::string str{stream.str()};
|
const std::string str{stream.str()};
|
||||||
size_t pos;
|
size_t pos;
|
||||||
|
@ -871,9 +856,9 @@ BOOST_AUTO_TEST_CASE(remove_invalid)
|
||||||
BOOST_REQUIRE(pos + sizeof(tried2_raw_replacement) <= stream.size());
|
BOOST_REQUIRE(pos + sizeof(tried2_raw_replacement) <= stream.size());
|
||||||
memcpy(stream.data() + pos, tried2_raw_replacement, sizeof(tried2_raw_replacement));
|
memcpy(stream.data() + pos, tried2_raw_replacement, sizeof(tried2_raw_replacement));
|
||||||
|
|
||||||
addrman.Clear();
|
addrman = std::make_unique<CAddrManTest>();
|
||||||
stream >> addrman;
|
stream >> *addrman;
|
||||||
BOOST_CHECK_EQUAL(addrman.size(), 2);
|
BOOST_CHECK_EQUAL(addrman->size(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
|
BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
|
||||||
|
@ -1083,13 +1068,12 @@ BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
|
||||||
BOOST_CHECK(addrman1.size() == 1);
|
BOOST_CHECK(addrman1.size() == 1);
|
||||||
BOOST_CHECK(exceptionThrown);
|
BOOST_CHECK(exceptionThrown);
|
||||||
|
|
||||||
// Test that CAddrDB::Read leaves addrman in a clean state if de-serialization fails.
|
// Test that CAddrDB::Read fails if peers.dat is corrupt
|
||||||
CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted);
|
CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted);
|
||||||
|
|
||||||
CAddrMan addrman2(/* deterministic */ false, /* consistency_check_ratio */ 100);
|
CAddrMan addrman2(/* deterministic */ false, /* consistency_check_ratio */ 100);
|
||||||
BOOST_CHECK(addrman2.size() == 0);
|
BOOST_CHECK(addrman2.size() == 0);
|
||||||
BOOST_CHECK(!CAddrDB::Read(addrman2, ssPeers2));
|
BOOST_CHECK(!CAddrDB::Read(addrman2, ssPeers2));
|
||||||
BOOST_CHECK(addrman2.size() == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -228,24 +228,22 @@ FUZZ_TARGET_INIT(addrman, initialize_addrman)
|
||||||
{
|
{
|
||||||
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
FuzzedDataProvider fuzzed_data_provider(buffer.data(), buffer.size());
|
||||||
SetMockTime(ConsumeTime(fuzzed_data_provider));
|
SetMockTime(ConsumeTime(fuzzed_data_provider));
|
||||||
CAddrManDeterministic addr_man{fuzzed_data_provider};
|
auto addr_man_ptr = std::make_unique<CAddrManDeterministic>(fuzzed_data_provider);
|
||||||
if (fuzzed_data_provider.ConsumeBool()) {
|
if (fuzzed_data_provider.ConsumeBool()) {
|
||||||
const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
|
const std::vector<uint8_t> serialized_data{ConsumeRandomLengthByteVector(fuzzed_data_provider)};
|
||||||
CDataStream ds(serialized_data, SER_DISK, INIT_PROTO_VERSION);
|
CDataStream ds(serialized_data, SER_DISK, INIT_PROTO_VERSION);
|
||||||
const auto ser_version{fuzzed_data_provider.ConsumeIntegral<int32_t>()};
|
const auto ser_version{fuzzed_data_provider.ConsumeIntegral<int32_t>()};
|
||||||
ds.SetVersion(ser_version);
|
ds.SetVersion(ser_version);
|
||||||
try {
|
try {
|
||||||
ds >> addr_man;
|
ds >> *addr_man_ptr;
|
||||||
} catch (const std::ios_base::failure&) {
|
} catch (const std::ios_base::failure&) {
|
||||||
addr_man.Clear();
|
addr_man_ptr = std::make_unique<CAddrManDeterministic>(fuzzed_data_provider);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
CAddrManDeterministic& addr_man = *addr_man_ptr;
|
||||||
while (fuzzed_data_provider.ConsumeBool()) {
|
while (fuzzed_data_provider.ConsumeBool()) {
|
||||||
CallOneOf(
|
CallOneOf(
|
||||||
fuzzed_data_provider,
|
fuzzed_data_provider,
|
||||||
[&] {
|
|
||||||
addr_man.Clear();
|
|
||||||
},
|
|
||||||
[&] {
|
[&] {
|
||||||
addr_man.ResolveCollisions();
|
addr_man.ResolveCollisions();
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Reference in a new issue