diff options
author | Vasil Dimov <vd@FreeBSD.org> | 2021-06-07 12:45:35 +0200 |
---|---|---|
committer | Vasil Dimov <vd@FreeBSD.org> | 2021-06-07 14:42:11 +0200 |
commit | 00b875ba9414463d0041da6924fd9b54d6a06dee (patch) | |
tree | 76c98674e9d4881ef66da84d107aa05dd1a9f7c1 /src | |
parent | bdb62096f0109b2ec76849d33d6cf7187dea299f (diff) | |
download | bitcoin-00b875ba9414463d0041da6924fd9b54d6a06dee.tar.xz |
addrman: remove invalid addresses when unserializing
The Tor v2 addresses, left over from when Tor v2 was supported will be
unserialized as a dummy, invalid `::` (all zeros) IPv6 address. Remove
them so that they do not take up space in addrman.
Diffstat (limited to 'src')
-rw-r--r-- | src/addrman.cpp | 32 | ||||
-rw-r--r-- | src/addrman.h | 5 | ||||
-rw-r--r-- | src/test/addrman_tests.cpp | 40 |
3 files changed, 77 insertions, 0 deletions
diff --git a/src/addrman.cpp b/src/addrman.cpp index 14b412a038..24531e8a6f 100644 --- a/src/addrman.cpp +++ b/src/addrman.cpp @@ -75,6 +75,38 @@ double CAddrInfo::GetChance(int64_t nNow) const return fChance; } +void CAddrMan::RemoveInvalid() +{ + for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; ++bucket) { + for (size_t i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) { + const auto id = vvNew[bucket][i]; + if (id != -1 && !mapInfo[id].IsValid()) { + ClearNew(bucket, i); + } + } + } + + for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; ++bucket) { + for (size_t i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) { + const auto id = vvTried[bucket][i]; + if (id == -1) { + continue; + } + const auto& addr_info = mapInfo[id]; + if (addr_info.IsValid()) { + continue; + } + vvTried[bucket][i] = -1; + --nTried; + SwapRandom(addr_info.nRandomPos, vRandom.size() - 1); + vRandom.pop_back(); + mapAddr.erase(addr_info); + mapInfo.erase(id); + m_tried_collisions.erase(id); + } + } +} + CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId) { std::map<CNetAddr, int>::iterator it = mapAddr.find(addr); diff --git a/src/addrman.h b/src/addrman.h index 41994288db..54ccd5f8f2 100644 --- a/src/addrman.h +++ b/src/addrman.h @@ -448,6 +448,8 @@ public: LogPrint(BCLog::ADDRMAN, "addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost); } + RemoveInvalid(); + Check(); } @@ -756,6 +758,9 @@ private: //! Update an entry's service bits. void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs); + //! Remove invalid addresses. + void RemoveInvalid() EXCLUSIVE_LOCKS_REQUIRED(cs); + friend class CAddrManTest; }; diff --git a/src/test/addrman_tests.cpp b/src/test/addrman_tests.cpp index 49b40924e0..6683065bb3 100644 --- a/src/test/addrman_tests.cpp +++ b/src/test/addrman_tests.cpp @@ -783,6 +783,46 @@ BOOST_AUTO_TEST_CASE(addrman_serialization) BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.second != bucketAndEntry_asmap1_deser_addr2.second); } +BOOST_AUTO_TEST_CASE(remove_invalid) +{ + // Confirm that invalid addresses are ignored in unserialization. + + CAddrManTest addrman; + CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); + + const CAddress new1{ResolveService("5.5.5.5"), NODE_NONE}; + const CAddress new2{ResolveService("6.6.6.6"), NODE_NONE}; + const CAddress tried1{ResolveService("7.7.7.7"), NODE_NONE}; + const CAddress tried2{ResolveService("8.8.8.8"), NODE_NONE}; + + addrman.Add({new1, tried1, new2, tried2}, CNetAddr{}); + addrman.Good(tried1); + addrman.Good(tried2); + BOOST_REQUIRE_EQUAL(addrman.size(), 4); + + stream << addrman; + + const std::string str{stream.str()}; + size_t pos; + + const char new2_raw[]{6, 6, 6, 6}; + const uint8_t new2_raw_replacement[]{0, 0, 0, 0}; // 0.0.0.0 is !IsValid() + pos = str.find(new2_raw, 0, sizeof(new2_raw)); + BOOST_REQUIRE(pos != std::string::npos); + BOOST_REQUIRE(pos + sizeof(new2_raw_replacement) <= stream.size()); + memcpy(stream.data() + pos, new2_raw_replacement, sizeof(new2_raw_replacement)); + + const char tried2_raw[]{8, 8, 8, 8}; + const uint8_t tried2_raw_replacement[]{255, 255, 255, 255}; // 255.255.255.255 is !IsValid() + pos = str.find(tried2_raw, 0, sizeof(tried2_raw)); + BOOST_REQUIRE(pos != std::string::npos); + BOOST_REQUIRE(pos + sizeof(tried2_raw_replacement) <= stream.size()); + memcpy(stream.data() + pos, tried2_raw_replacement, sizeof(tried2_raw_replacement)); + + addrman.Clear(); + stream >> addrman; + BOOST_CHECK_EQUAL(addrman.size(), 2); +} BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision) { |