LCOV - code coverage report
Current view: top level - src/test - addrman_tests.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 616 618 99.7 %
Date: 2022-04-21 14:51:19 Functions: 25 25 100.0 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 50 50 100.0 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2012-2021 The Bitcoin Core developers
#       2                 :            : // Distributed under the MIT software license, see the accompanying
#       3                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       4                 :            : 
#       5                 :            : #include <addrdb.h>
#       6                 :            : #include <addrman.h>
#       7                 :            : #include <addrman_impl.h>
#       8                 :            : #include <chainparams.h>
#       9                 :            : #include <clientversion.h>
#      10                 :            : #include <hash.h>
#      11                 :            : #include <netbase.h>
#      12                 :            : #include <random.h>
#      13                 :            : #include <test/data/asmap.raw.h>
#      14                 :            : #include <test/util/setup_common.h>
#      15                 :            : #include <util/asmap.h>
#      16                 :            : #include <util/string.h>
#      17                 :            : 
#      18                 :            : #include <boost/test/unit_test.hpp>
#      19                 :            : 
#      20                 :            : #include <optional>
#      21                 :            : #include <string>
#      22                 :            : 
#      23                 :            : using namespace std::literals;
#      24                 :            : using node::NodeContext;
#      25                 :            : 
#      26                 :            : static const std::vector<bool> EMPTY_ASMAP;
#      27                 :            : static const bool DETERMINISTIC{true};
#      28                 :            : 
#      29                 :            : static int32_t GetCheckRatio(const NodeContext& node_ctx)
#      30                 :         40 : {
#      31                 :         40 :     return std::clamp<int32_t>(node_ctx.args->GetIntArg("-checkaddrman", 100), 0, 1000000);
#      32                 :         40 : }
#      33                 :            : 
#      34                 :            : static CNetAddr ResolveIP(const std::string& ip)
#      35                 :      13630 : {
#      36                 :      13630 :     CNetAddr addr;
#      37                 :      13630 :     BOOST_CHECK_MESSAGE(LookupHost(ip, addr, false), strprintf("failed to resolve: %s", ip));
#      38                 :      13630 :     return addr;
#      39                 :      13630 : }
#      40                 :            : 
#      41                 :            : static CService ResolveService(const std::string& ip, uint16_t port = 0)
#      42                 :      13252 : {
#      43                 :      13252 :     CService serv;
#      44                 :      13252 :     BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port));
#      45                 :      13252 :     return serv;
#      46                 :      13252 : }
#      47                 :            : 
#      48                 :            : 
#      49                 :            : static std::vector<bool> FromBytes(const unsigned char* source, int vector_size)
#      50                 :          6 : {
#      51                 :          6 :     std::vector<bool> result(vector_size);
#      52         [ +  + ]:        360 :     for (int byte_i = 0; byte_i < vector_size / 8; ++byte_i) {
#      53                 :        354 :         unsigned char cur_byte = source[byte_i];
#      54         [ +  + ]:       3186 :         for (int bit_i = 0; bit_i < 8; ++bit_i) {
#      55                 :       2832 :             result[byte_i * 8 + bit_i] = (cur_byte >> bit_i) & 1;
#      56                 :       2832 :         }
#      57                 :        354 :     }
#      58                 :          6 :     return result;
#      59                 :          6 : }
#      60                 :            : 
#      61                 :            : BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
#      62                 :            : 
#      63                 :            : BOOST_AUTO_TEST_CASE(addrman_simple)
#      64                 :          2 : {
#      65                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#      66                 :            : 
#      67                 :          2 :     CNetAddr source = ResolveIP("252.2.2.2");
#      68                 :            : 
#      69                 :            :     // Test: Does Addrman respond correctly when empty.
#      70                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 0U);
#      71                 :          2 :     auto addr_null = addrman->Select().first;
#      72                 :          2 :     BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
#      73                 :            : 
#      74                 :            :     // Test: Does Addrman::Add work as expected.
#      75                 :          2 :     CService addr1 = ResolveService("250.1.1.1", 8333);
#      76                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
#      77                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 1U);
#      78                 :          2 :     auto addr_ret1 = addrman->Select().first;
#      79                 :          2 :     BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
#      80                 :            : 
#      81                 :            :     // Test: Does IP address deduplication work correctly.
#      82                 :            :     //  Expected dup IP should not be added.
#      83                 :          2 :     CService addr1_dup = ResolveService("250.1.1.1", 8333);
#      84                 :          2 :     BOOST_CHECK(!addrman->Add({CAddress(addr1_dup, NODE_NONE)}, source));
#      85                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 1U);
#      86                 :            : 
#      87                 :            : 
#      88                 :            :     // Test: New table has one addr and we add a diff addr we should
#      89                 :            :     //  have at least one addr.
#      90                 :            :     // Note that addrman's size cannot be tested reliably after insertion, as
#      91                 :            :     // hash collisions may occur. But we can always be sure of at least one
#      92                 :            :     // success.
#      93                 :            : 
#      94                 :          2 :     CService addr2 = ResolveService("250.1.1.2", 8333);
#      95                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
#      96                 :          2 :     BOOST_CHECK(addrman->size() >= 1);
#      97                 :            : 
#      98                 :            :     // Test: reset addrman and test AddrMan::Add multiple addresses works as expected
#      99                 :          2 :     addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     100                 :          2 :     std::vector<CAddress> vAddr;
#     101                 :          2 :     vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
#     102                 :          2 :     vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
#     103                 :          2 :     BOOST_CHECK(addrman->Add(vAddr, source));
#     104                 :          2 :     BOOST_CHECK(addrman->size() >= 1);
#     105                 :          2 : }
#     106                 :            : 
#     107                 :            : BOOST_AUTO_TEST_CASE(addrman_ports)
#     108                 :          2 : {
#     109                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     110                 :            : 
#     111                 :          2 :     CNetAddr source = ResolveIP("252.2.2.2");
#     112                 :            : 
#     113                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 0U);
#     114                 :            : 
#     115                 :            :     // Test 7; Addr with same IP but diff port does not replace existing addr.
#     116                 :          2 :     CService addr1 = ResolveService("250.1.1.1", 8333);
#     117                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
#     118                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 1U);
#     119                 :            : 
#     120                 :          2 :     CService addr1_port = ResolveService("250.1.1.1", 8334);
#     121                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr1_port, NODE_NONE)}, source));
#     122                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 2U);
#     123                 :          2 :     auto addr_ret2 = addrman->Select().first;
#     124                 :          2 :     BOOST_CHECK(addr_ret2.ToString() == "250.1.1.1:8333" || addr_ret2.ToString() == "250.1.1.1:8334");
#     125                 :            : 
#     126                 :            :     // Test: Add same IP but diff port to tried table; this converts the entry with
#     127                 :            :     // the specified port to tried, but not the other.
#     128                 :          2 :     addrman->Good(CAddress(addr1_port, NODE_NONE));
#     129                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 2U);
#     130                 :          2 :     bool newOnly = true;
#     131                 :          2 :     auto addr_ret3 = addrman->Select(newOnly).first;
#     132                 :          2 :     BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
#     133                 :          2 : }
#     134                 :            : 
#     135                 :            : 
#     136                 :            : BOOST_AUTO_TEST_CASE(addrman_select)
#     137                 :          2 : {
#     138                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     139                 :            : 
#     140                 :          2 :     CNetAddr source = ResolveIP("252.2.2.2");
#     141                 :            : 
#     142                 :            :     // Test: Select from new with 1 addr in new.
#     143                 :          2 :     CService addr1 = ResolveService("250.1.1.1", 8333);
#     144                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
#     145                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 1U);
#     146                 :            : 
#     147                 :          2 :     bool newOnly = true;
#     148                 :          2 :     auto addr_ret1 = addrman->Select(newOnly).first;
#     149                 :          2 :     BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
#     150                 :            : 
#     151                 :            :     // Test: move addr to tried, select from new expected nothing returned.
#     152                 :          2 :     BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));
#     153                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 1U);
#     154                 :          2 :     auto addr_ret2 = addrman->Select(newOnly).first;
#     155                 :          2 :     BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0");
#     156                 :            : 
#     157                 :          2 :     auto addr_ret3 = addrman->Select().first;
#     158                 :          2 :     BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
#     159                 :            : 
#     160                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 1U);
#     161                 :            : 
#     162                 :            : 
#     163                 :            :     // Add three addresses to new table.
#     164                 :          2 :     CService addr2 = ResolveService("250.3.1.1", 8333);
#     165                 :          2 :     CService addr3 = ResolveService("250.3.2.2", 9999);
#     166                 :          2 :     CService addr4 = ResolveService("250.3.3.3", 9999);
#     167                 :            : 
#     168                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
#     169                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr3, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
#     170                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr4, NODE_NONE)}, ResolveService("250.4.1.1", 8333)));
#     171                 :            : 
#     172                 :            :     // Add three addresses to tried table.
#     173                 :          2 :     CService addr5 = ResolveService("250.4.4.4", 8333);
#     174                 :          2 :     CService addr6 = ResolveService("250.4.5.5", 7777);
#     175                 :          2 :     CService addr7 = ResolveService("250.4.6.6", 8333);
#     176                 :            : 
#     177                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr5, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
#     178                 :          2 :     BOOST_CHECK(addrman->Good(CAddress(addr5, NODE_NONE)));
#     179                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr6, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
#     180                 :          2 :     BOOST_CHECK(addrman->Good(CAddress(addr6, NODE_NONE)));
#     181                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr7, NODE_NONE)}, ResolveService("250.1.1.3", 8333)));
#     182                 :          2 :     BOOST_CHECK(addrman->Good(CAddress(addr7, NODE_NONE)));
#     183                 :            : 
#     184                 :            :     // Test: 6 addrs + 1 addr from last test = 7.
#     185                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 7U);
#     186                 :            : 
#     187                 :            :     // Test: Select pulls from new and tried regardless of port number.
#     188                 :          2 :     std::set<uint16_t> ports;
#     189         [ +  + ]:         42 :     for (int i = 0; i < 20; ++i) {
#     190                 :         40 :         ports.insert(addrman->Select().first.GetPort());
#     191                 :         40 :     }
#     192                 :          2 :     BOOST_CHECK_EQUAL(ports.size(), 3U);
#     193                 :          2 : }
#     194                 :            : 
#     195                 :            : BOOST_AUTO_TEST_CASE(addrman_new_collisions)
#     196                 :          2 : {
#     197                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     198                 :            : 
#     199                 :          2 :     CNetAddr source = ResolveIP("252.2.2.2");
#     200                 :            : 
#     201                 :          2 :     uint32_t num_addrs{0};
#     202                 :            : 
#     203                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
#     204                 :            : 
#     205         [ +  + ]:         46 :     while (num_addrs < 22) { // Magic number! 250.1.1.1 - 250.1.1.22 do not collide with deterministic key = 1
#     206                 :         44 :         CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
#     207                 :         44 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
#     208                 :            : 
#     209                 :            :         // Test: No collision in new table yet.
#     210                 :         44 :         BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
#     211                 :         44 :     }
#     212                 :            : 
#     213                 :            :     // Test: new table collision!
#     214                 :          2 :     CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
#     215                 :          2 :     uint32_t collisions{1};
#     216                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
#     217                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), num_addrs - collisions);
#     218                 :            : 
#     219                 :          2 :     CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
#     220                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
#     221                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), num_addrs - collisions);
#     222                 :          2 : }
#     223                 :            : 
#     224                 :            : BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
#     225                 :          2 : {
#     226                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     227                 :          2 :     CAddress addr{CAddress(ResolveService("253.3.3.3", 8333), NODE_NONE)};
#     228                 :          2 :     int64_t start_time{GetAdjustedTime()};
#     229                 :          2 :     addr.nTime = start_time;
#     230                 :            : 
#     231                 :            :     // test that multiplicity stays at 1 if nTime doesn't increase
#     232         [ +  + ]:         40 :     for (unsigned int i = 1; i < 20; ++i) {
#     233                 :         38 :         std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};
#     234                 :         38 :         CNetAddr source{ResolveIP(addr_ip)};
#     235                 :         38 :         addrman->Add({addr}, source);
#     236                 :         38 :     }
#     237                 :          2 :     AddressPosition addr_pos = addrman->FindAddressEntry(addr).value();
#     238                 :          2 :     BOOST_CHECK_EQUAL(addr_pos.multiplicity, 1U);
#     239                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 1U);
#     240                 :            : 
#     241                 :            :     // if nTime increases, an addr can occur in up to 8 buckets
#     242                 :            :     // The acceptance probability decreases exponentially with existing multiplicity -
#     243                 :            :     // choose number of iterations such that it gets to 8 with deterministic addrman.
#     244         [ +  + ]:        800 :     for (unsigned int i = 1; i < 400; ++i) {
#     245                 :        798 :         std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};
#     246                 :        798 :         CNetAddr source{ResolveIP(addr_ip)};
#     247                 :        798 :         addr.nTime = start_time + i;
#     248                 :        798 :         addrman->Add({addr}, source);
#     249                 :        798 :     }
#     250                 :          2 :     AddressPosition addr_pos_multi = addrman->FindAddressEntry(addr).value();
#     251                 :          2 :     BOOST_CHECK_EQUAL(addr_pos_multi.multiplicity, 8U);
#     252                 :            :     // multiplicity doesn't affect size
#     253                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 1U);
#     254                 :          2 : }
#     255                 :            : 
#     256                 :            : BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
#     257                 :          2 : {
#     258                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     259                 :            : 
#     260                 :          2 :     CNetAddr source = ResolveIP("252.2.2.2");
#     261                 :            : 
#     262                 :          2 :     uint32_t num_addrs{0};
#     263                 :            : 
#     264                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), num_addrs);
#     265                 :            : 
#     266         [ +  + ]:         72 :     while (num_addrs < 35) { // Magic number! 250.1.1.1 - 250.1.1.35 do not collide in tried with deterministic key = 1
#     267                 :         70 :         CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
#     268                 :         70 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
#     269                 :            : 
#     270                 :            :         // Test: Add to tried without collision
#     271                 :         70 :         BOOST_CHECK(addrman->Good(CAddress(addr, NODE_NONE)));
#     272                 :            : 
#     273                 :         70 :     }
#     274                 :            : 
#     275                 :            :     // Test: Unable to add to tried table due to collision!
#     276                 :          2 :     CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
#     277                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
#     278                 :          2 :     BOOST_CHECK(!addrman->Good(CAddress(addr1, NODE_NONE)));
#     279                 :            : 
#     280                 :            :     // Test: Add the next address to tried without collision
#     281                 :          2 :     CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
#     282                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
#     283                 :          2 :     BOOST_CHECK(addrman->Good(CAddress(addr2, NODE_NONE)));
#     284                 :          2 : }
#     285                 :            : 
#     286                 :            : 
#     287                 :            : BOOST_AUTO_TEST_CASE(addrman_getaddr)
#     288                 :          2 : {
#     289                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     290                 :            : 
#     291                 :            :     // Test: Sanity check, GetAddr should never return anything if addrman
#     292                 :            :     //  is empty.
#     293                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 0U);
#     294                 :          2 :     std::vector<CAddress> vAddr1 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
#     295                 :          2 :     BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
#     296                 :            : 
#     297                 :          2 :     CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
#     298                 :          2 :     addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
#     299                 :          2 :     CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
#     300                 :          2 :     addr2.nTime = GetAdjustedTime();
#     301                 :          2 :     CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
#     302                 :          2 :     addr3.nTime = GetAdjustedTime();
#     303                 :          2 :     CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
#     304                 :          2 :     addr4.nTime = GetAdjustedTime();
#     305                 :          2 :     CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
#     306                 :          2 :     addr5.nTime = GetAdjustedTime();
#     307                 :          2 :     CNetAddr source1 = ResolveIP("250.1.2.1");
#     308                 :          2 :     CNetAddr source2 = ResolveIP("250.2.3.3");
#     309                 :            : 
#     310                 :            :     // Test: Ensure GetAddr works with new addresses.
#     311                 :          2 :     BOOST_CHECK(addrman->Add({addr1, addr3, addr5}, source1));
#     312                 :          2 :     BOOST_CHECK(addrman->Add({addr2, addr4}, source2));
#     313                 :            : 
#     314                 :          2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 5U);
#     315                 :            :     // Net processing asks for 23% of addresses. 23% of 5 is 1 rounded down.
#     316                 :          2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt).size(), 1U);
#     317                 :            : 
#     318                 :            :     // Test: Ensure GetAddr works with new and tried addresses.
#     319                 :          2 :     BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));
#     320                 :          2 :     BOOST_CHECK(addrman->Good(CAddress(addr2, NODE_NONE)));
#     321                 :          2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 5U);
#     322                 :          2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt).size(), 1U);
#     323                 :            : 
#     324                 :            :     // Test: Ensure GetAddr still returns 23% when addrman has many addrs.
#     325         [ +  + ]:       4096 :     for (unsigned int i = 1; i < (8 * 256); i++) {
#     326                 :       4094 :         int octet1 = i % 256;
#     327                 :       4094 :         int octet2 = i >> 8 % 256;
#     328                 :       4094 :         std::string strAddr = ToString(octet1) + "." + ToString(octet2) + ".1.23";
#     329                 :       4094 :         CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
#     330                 :            : 
#     331                 :            :         // Ensure that for all addrs in addrman, isTerrible == false.
#     332                 :       4094 :         addr.nTime = GetAdjustedTime();
#     333                 :       4094 :         addrman->Add({addr}, ResolveIP(strAddr));
#     334         [ +  + ]:       4094 :         if (i % 8 == 0)
#     335                 :        510 :             addrman->Good(addr);
#     336                 :       4094 :     }
#     337                 :          2 :     std::vector<CAddress> vAddr = addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt);
#     338                 :            : 
#     339                 :          2 :     size_t percent23 = (addrman->size() * 23) / 100;
#     340                 :          2 :     BOOST_CHECK_EQUAL(vAddr.size(), percent23);
#     341                 :          2 :     BOOST_CHECK_EQUAL(vAddr.size(), 461U);
#     342                 :            :     // (Addrman.size() < number of addresses added) due to address collisions.
#     343                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 2006U);
#     344                 :          2 : }
#     345                 :            : 
#     346                 :            : 
#     347                 :            : BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
#     348                 :          2 : {
#     349                 :          2 :     CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
#     350                 :          2 :     CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
#     351                 :            : 
#     352                 :          2 :     CNetAddr source1 = ResolveIP("250.1.1.1");
#     353                 :            : 
#     354                 :            : 
#     355                 :          2 :     AddrInfo info1 = AddrInfo(addr1, source1);
#     356                 :            : 
#     357                 :          2 :     uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
#     358                 :          2 :     uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
#     359                 :            : 
#     360                 :          2 :     std::vector<bool> asmap; // use /16
#     361                 :            : 
#     362                 :          2 :     BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, asmap), 40);
#     363                 :            : 
#     364                 :            :     // Test: Make sure key actually randomizes bucket placement. A fail on
#     365                 :            :     //  this test could be a security issue.
#     366                 :          2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info1.GetTriedBucket(nKey2, asmap));
#     367                 :            : 
#     368                 :            :     // Test: Two addresses with same IP but different ports can map to
#     369                 :            :     //  different buckets because they have different keys.
#     370                 :          2 :     AddrInfo info2 = AddrInfo(addr2, source1);
#     371                 :            : 
#     372                 :          2 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
#     373                 :          2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info2.GetTriedBucket(nKey1, asmap));
#     374                 :            : 
#     375                 :          2 :     std::set<int> buckets;
#     376         [ +  + ]:        512 :     for (int i = 0; i < 255; i++) {
#     377                 :        510 :         AddrInfo infoi = AddrInfo(
#     378                 :        510 :             CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
#     379                 :        510 :             ResolveIP("250.1.1." + ToString(i)));
#     380                 :        510 :         int bucket = infoi.GetTriedBucket(nKey1, asmap);
#     381                 :        510 :         buckets.insert(bucket);
#     382                 :        510 :     }
#     383                 :            :     // Test: IP addresses in the same /16 prefix should
#     384                 :            :     // never get more than 8 buckets with legacy grouping
#     385                 :          2 :     BOOST_CHECK_EQUAL(buckets.size(), 8U);
#     386                 :            : 
#     387                 :          2 :     buckets.clear();
#     388         [ +  + ]:        512 :     for (int j = 0; j < 255; j++) {
#     389                 :        510 :         AddrInfo infoj = AddrInfo(
#     390                 :        510 :             CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
#     391                 :        510 :             ResolveIP("250." + ToString(j) + ".1.1"));
#     392                 :        510 :         int bucket = infoj.GetTriedBucket(nKey1, asmap);
#     393                 :        510 :         buckets.insert(bucket);
#     394                 :        510 :     }
#     395                 :            :     // Test: IP addresses in the different /16 prefix should map to more than
#     396                 :            :     // 8 buckets with legacy grouping
#     397                 :          2 :     BOOST_CHECK_EQUAL(buckets.size(), 160U);
#     398                 :          2 : }
#     399                 :            : 
#     400                 :            : BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket_legacy)
#     401                 :          2 : {
#     402                 :          2 :     CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
#     403                 :          2 :     CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
#     404                 :            : 
#     405                 :          2 :     CNetAddr source1 = ResolveIP("250.1.2.1");
#     406                 :            : 
#     407                 :          2 :     AddrInfo info1 = AddrInfo(addr1, source1);
#     408                 :            : 
#     409                 :          2 :     uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
#     410                 :          2 :     uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
#     411                 :            : 
#     412                 :          2 :     std::vector<bool> asmap; // use /16
#     413                 :            : 
#     414                 :            :     // Test: Make sure the buckets are what we expect
#     415                 :          2 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), 786);
#     416                 :          2 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, asmap), 786);
#     417                 :            : 
#     418                 :            :     // Test: Make sure key actually randomizes bucket placement. A fail on
#     419                 :            :     //  this test could be a security issue.
#     420                 :          2 :     BOOST_CHECK(info1.GetNewBucket(nKey1, asmap) != info1.GetNewBucket(nKey2, asmap));
#     421                 :            : 
#     422                 :            :     // Test: Ports should not affect bucket placement in the addr
#     423                 :          2 :     AddrInfo info2 = AddrInfo(addr2, source1);
#     424                 :          2 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
#     425                 :          2 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), info2.GetNewBucket(nKey1, asmap));
#     426                 :            : 
#     427                 :          2 :     std::set<int> buckets;
#     428         [ +  + ]:        512 :     for (int i = 0; i < 255; i++) {
#     429                 :        510 :         AddrInfo infoi = AddrInfo(
#     430                 :        510 :             CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
#     431                 :        510 :             ResolveIP("250.1.1." + ToString(i)));
#     432                 :        510 :         int bucket = infoi.GetNewBucket(nKey1, asmap);
#     433                 :        510 :         buckets.insert(bucket);
#     434                 :        510 :     }
#     435                 :            :     // Test: IP addresses in the same group (\16 prefix for IPv4) should
#     436                 :            :     //  always map to the same bucket.
#     437                 :          2 :     BOOST_CHECK_EQUAL(buckets.size(), 1U);
#     438                 :            : 
#     439                 :          2 :     buckets.clear();
#     440         [ +  + ]:       2042 :     for (int j = 0; j < 4 * 255; j++) {
#     441                 :       2040 :         AddrInfo infoj = AddrInfo(CAddress(
#     442                 :       2040 :                                         ResolveService(
#     443                 :       2040 :                                             ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
#     444                 :       2040 :             ResolveIP("251.4.1.1"));
#     445                 :       2040 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
#     446                 :       2040 :         buckets.insert(bucket);
#     447                 :       2040 :     }
#     448                 :            :     // Test: IP addresses in the same source groups should map to NO MORE
#     449                 :            :     //  than 64 buckets.
#     450                 :          2 :     BOOST_CHECK(buckets.size() <= 64);
#     451                 :            : 
#     452                 :          2 :     buckets.clear();
#     453         [ +  + ]:        512 :     for (int p = 0; p < 255; p++) {
#     454                 :        510 :         AddrInfo infoj = AddrInfo(
#     455                 :        510 :             CAddress(ResolveService("250.1.1.1"), NODE_NONE),
#     456                 :        510 :             ResolveIP("250." + ToString(p) + ".1.1"));
#     457                 :        510 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
#     458                 :        510 :         buckets.insert(bucket);
#     459                 :        510 :     }
#     460                 :            :     // Test: IP addresses in the different source groups should map to MORE
#     461                 :            :     //  than 64 buckets.
#     462                 :          2 :     BOOST_CHECK(buckets.size() > 64);
#     463                 :          2 : }
#     464                 :            : 
#     465                 :            : // The following three test cases use asmap.raw
#     466                 :            : // We use an artificial minimal mock mapping
#     467                 :            : // 250.0.0.0/8 AS1000
#     468                 :            : // 101.1.0.0/16 AS1
#     469                 :            : // 101.2.0.0/16 AS2
#     470                 :            : // 101.3.0.0/16 AS3
#     471                 :            : // 101.4.0.0/16 AS4
#     472                 :            : // 101.5.0.0/16 AS5
#     473                 :            : // 101.6.0.0/16 AS6
#     474                 :            : // 101.7.0.0/16 AS7
#     475                 :            : // 101.8.0.0/16 AS8
#     476                 :            : BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
#     477                 :          2 : {
#     478                 :          2 :     CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
#     479                 :          2 :     CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
#     480                 :            : 
#     481                 :          2 :     CNetAddr source1 = ResolveIP("250.1.1.1");
#     482                 :            : 
#     483                 :            : 
#     484                 :          2 :     AddrInfo info1 = AddrInfo(addr1, source1);
#     485                 :            : 
#     486                 :          2 :     uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
#     487                 :          2 :     uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
#     488                 :            : 
#     489                 :          2 :     std::vector<bool> asmap = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
#     490                 :            : 
#     491                 :          2 :     BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, asmap), 236);
#     492                 :            : 
#     493                 :            :     // Test: Make sure key actually randomizes bucket placement. A fail on
#     494                 :            :     //  this test could be a security issue.
#     495                 :          2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info1.GetTriedBucket(nKey2, asmap));
#     496                 :            : 
#     497                 :            :     // Test: Two addresses with same IP but different ports can map to
#     498                 :            :     //  different buckets because they have different keys.
#     499                 :          2 :     AddrInfo info2 = AddrInfo(addr2, source1);
#     500                 :            : 
#     501                 :          2 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
#     502                 :          2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info2.GetTriedBucket(nKey1, asmap));
#     503                 :            : 
#     504                 :          2 :     std::set<int> buckets;
#     505         [ +  + ]:        512 :     for (int j = 0; j < 255; j++) {
#     506                 :        510 :         AddrInfo infoj = AddrInfo(
#     507                 :        510 :             CAddress(ResolveService("101." + ToString(j) + ".1.1"), NODE_NONE),
#     508                 :        510 :             ResolveIP("101." + ToString(j) + ".1.1"));
#     509                 :        510 :         int bucket = infoj.GetTriedBucket(nKey1, asmap);
#     510                 :        510 :         buckets.insert(bucket);
#     511                 :        510 :     }
#     512                 :            :     // Test: IP addresses in the different /16 prefix MAY map to more than
#     513                 :            :     // 8 buckets.
#     514                 :          2 :     BOOST_CHECK(buckets.size() > 8);
#     515                 :            : 
#     516                 :          2 :     buckets.clear();
#     517         [ +  + ]:        512 :     for (int j = 0; j < 255; j++) {
#     518                 :        510 :         AddrInfo infoj = AddrInfo(
#     519                 :        510 :             CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
#     520                 :        510 :             ResolveIP("250." + ToString(j) + ".1.1"));
#     521                 :        510 :         int bucket = infoj.GetTriedBucket(nKey1, asmap);
#     522                 :        510 :         buckets.insert(bucket);
#     523                 :        510 :     }
#     524                 :            :     // Test: IP addresses in the different /16 prefix MAY NOT map to more than
#     525                 :            :     // 8 buckets.
#     526                 :          2 :     BOOST_CHECK(buckets.size() == 8);
#     527                 :          2 : }
#     528                 :            : 
#     529                 :            : BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
#     530                 :          2 : {
#     531                 :          2 :     CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
#     532                 :          2 :     CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
#     533                 :            : 
#     534                 :          2 :     CNetAddr source1 = ResolveIP("250.1.2.1");
#     535                 :            : 
#     536                 :          2 :     AddrInfo info1 = AddrInfo(addr1, source1);
#     537                 :            : 
#     538                 :          2 :     uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
#     539                 :          2 :     uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
#     540                 :            : 
#     541                 :          2 :     std::vector<bool> asmap = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
#     542                 :            : 
#     543                 :            :     // Test: Make sure the buckets are what we expect
#     544                 :          2 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), 795);
#     545                 :          2 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, asmap), 795);
#     546                 :            : 
#     547                 :            :     // Test: Make sure key actually randomizes bucket placement. A fail on
#     548                 :            :     //  this test could be a security issue.
#     549                 :          2 :     BOOST_CHECK(info1.GetNewBucket(nKey1, asmap) != info1.GetNewBucket(nKey2, asmap));
#     550                 :            : 
#     551                 :            :     // Test: Ports should not affect bucket placement in the addr
#     552                 :          2 :     AddrInfo info2 = AddrInfo(addr2, source1);
#     553                 :          2 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
#     554                 :          2 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), info2.GetNewBucket(nKey1, asmap));
#     555                 :            : 
#     556                 :          2 :     std::set<int> buckets;
#     557         [ +  + ]:        512 :     for (int i = 0; i < 255; i++) {
#     558                 :        510 :         AddrInfo infoi = AddrInfo(
#     559                 :        510 :             CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
#     560                 :        510 :             ResolveIP("250.1.1." + ToString(i)));
#     561                 :        510 :         int bucket = infoi.GetNewBucket(nKey1, asmap);
#     562                 :        510 :         buckets.insert(bucket);
#     563                 :        510 :     }
#     564                 :            :     // Test: IP addresses in the same /16 prefix
#     565                 :            :     // usually map to the same bucket.
#     566                 :          2 :     BOOST_CHECK_EQUAL(buckets.size(), 1U);
#     567                 :            : 
#     568                 :          2 :     buckets.clear();
#     569         [ +  + ]:       2042 :     for (int j = 0; j < 4 * 255; j++) {
#     570                 :       2040 :         AddrInfo infoj = AddrInfo(CAddress(
#     571                 :       2040 :                                         ResolveService(
#     572                 :       2040 :                                             ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
#     573                 :       2040 :             ResolveIP("251.4.1.1"));
#     574                 :       2040 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
#     575                 :       2040 :         buckets.insert(bucket);
#     576                 :       2040 :     }
#     577                 :            :     // Test: IP addresses in the same source /16 prefix should not map to more
#     578                 :            :     // than 64 buckets.
#     579                 :          2 :     BOOST_CHECK(buckets.size() <= 64);
#     580                 :            : 
#     581                 :          2 :     buckets.clear();
#     582         [ +  + ]:        512 :     for (int p = 0; p < 255; p++) {
#     583                 :        510 :         AddrInfo infoj = AddrInfo(
#     584                 :        510 :             CAddress(ResolveService("250.1.1.1"), NODE_NONE),
#     585                 :        510 :             ResolveIP("101." + ToString(p) + ".1.1"));
#     586                 :        510 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
#     587                 :        510 :         buckets.insert(bucket);
#     588                 :        510 :     }
#     589                 :            :     // Test: IP addresses in the different source /16 prefixes usually map to MORE
#     590                 :            :     // than 1 bucket.
#     591                 :          2 :     BOOST_CHECK(buckets.size() > 1);
#     592                 :            : 
#     593                 :          2 :     buckets.clear();
#     594         [ +  + ]:        512 :     for (int p = 0; p < 255; p++) {
#     595                 :        510 :         AddrInfo infoj = AddrInfo(
#     596                 :        510 :             CAddress(ResolveService("250.1.1.1"), NODE_NONE),
#     597                 :        510 :             ResolveIP("250." + ToString(p) + ".1.1"));
#     598                 :        510 :         int bucket = infoj.GetNewBucket(nKey1, asmap);
#     599                 :        510 :         buckets.insert(bucket);
#     600                 :        510 :     }
#     601                 :            :     // Test: IP addresses in the different source /16 prefixes sometimes map to NO MORE
#     602                 :            :     // than 1 bucket.
#     603                 :          2 :     BOOST_CHECK(buckets.size() == 1);
#     604                 :          2 : }
#     605                 :            : 
#     606                 :            : BOOST_AUTO_TEST_CASE(addrman_serialization)
#     607                 :          2 : {
#     608                 :          2 :     std::vector<bool> asmap1 = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
#     609                 :            : 
#     610                 :          2 :     const auto ratio = GetCheckRatio(m_node);
#     611                 :          2 :     auto addrman_asmap1 = std::make_unique<AddrMan>(asmap1, DETERMINISTIC, ratio);
#     612                 :          2 :     auto addrman_asmap1_dup = std::make_unique<AddrMan>(asmap1, DETERMINISTIC, ratio);
#     613                 :          2 :     auto addrman_noasmap = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, ratio);
#     614                 :            : 
#     615                 :          2 :     CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
#     616                 :            : 
#     617                 :          2 :     CAddress addr = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
#     618                 :          2 :     CNetAddr default_source;
#     619                 :            : 
#     620                 :          2 :     addrman_asmap1->Add({addr}, default_source);
#     621                 :            : 
#     622                 :          2 :     stream << *addrman_asmap1;
#     623                 :            :     // serizalizing/deserializing addrman with the same asmap
#     624                 :          2 :     stream >> *addrman_asmap1_dup;
#     625                 :            : 
#     626                 :          2 :     AddressPosition addr_pos1 = addrman_asmap1->FindAddressEntry(addr).value();
#     627                 :          2 :     AddressPosition addr_pos2 = addrman_asmap1_dup->FindAddressEntry(addr).value();
#     628                 :          2 :     BOOST_CHECK(addr_pos1.multiplicity != 0);
#     629                 :          2 :     BOOST_CHECK(addr_pos2.multiplicity != 0);
#     630                 :            : 
#     631                 :          2 :     BOOST_CHECK(addr_pos1 == addr_pos2);
#     632                 :            : 
#     633                 :            :     // deserializing asmaped peers.dat to non-asmaped addrman
#     634                 :          2 :     stream << *addrman_asmap1;
#     635                 :          2 :     stream >> *addrman_noasmap;
#     636                 :          2 :     AddressPosition addr_pos3 = addrman_noasmap->FindAddressEntry(addr).value();
#     637                 :          2 :     BOOST_CHECK(addr_pos3.multiplicity != 0);
#     638                 :          2 :     BOOST_CHECK(addr_pos1.bucket != addr_pos3.bucket);
#     639                 :          2 :     BOOST_CHECK(addr_pos1.position != addr_pos3.position);
#     640                 :            : 
#     641                 :            :     // deserializing non-asmaped peers.dat to asmaped addrman
#     642                 :          2 :     addrman_asmap1 = std::make_unique<AddrMan>(asmap1, DETERMINISTIC, ratio);
#     643                 :          2 :     addrman_noasmap = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, ratio);
#     644                 :          2 :     addrman_noasmap->Add({addr}, default_source);
#     645                 :          2 :     stream << *addrman_noasmap;
#     646                 :          2 :     stream >> *addrman_asmap1;
#     647                 :            : 
#     648                 :          2 :     AddressPosition addr_pos4 = addrman_asmap1->FindAddressEntry(addr).value();
#     649                 :          2 :     BOOST_CHECK(addr_pos4.multiplicity != 0);
#     650                 :          2 :     BOOST_CHECK(addr_pos4.bucket != addr_pos3.bucket);
#     651                 :          2 :     BOOST_CHECK(addr_pos4 == addr_pos2);
#     652                 :            : 
#     653                 :            :     // used to map to different buckets, now maps to the same bucket.
#     654                 :          2 :     addrman_asmap1 = std::make_unique<AddrMan>(asmap1, DETERMINISTIC, ratio);
#     655                 :          2 :     addrman_noasmap = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, ratio);
#     656                 :          2 :     CAddress addr1 = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
#     657                 :          2 :     CAddress addr2 = CAddress(ResolveService("250.2.1.1"), NODE_NONE);
#     658                 :          2 :     addrman_noasmap->Add({addr, addr2}, default_source);
#     659                 :          2 :     AddressPosition addr_pos5 = addrman_noasmap->FindAddressEntry(addr1).value();
#     660                 :          2 :     AddressPosition addr_pos6 = addrman_noasmap->FindAddressEntry(addr2).value();
#     661                 :          2 :     BOOST_CHECK(addr_pos5.bucket != addr_pos6.bucket);
#     662                 :          2 :     stream << *addrman_noasmap;
#     663                 :          2 :     stream >> *addrman_asmap1;
#     664                 :          2 :     AddressPosition addr_pos7 = addrman_asmap1->FindAddressEntry(addr1).value();
#     665                 :          2 :     AddressPosition addr_pos8 = addrman_asmap1->FindAddressEntry(addr2).value();
#     666                 :          2 :     BOOST_CHECK(addr_pos7.bucket == addr_pos8.bucket);
#     667                 :          2 :     BOOST_CHECK(addr_pos7.position != addr_pos8.position);
#     668                 :          2 : }
#     669                 :            : 
#     670                 :            : BOOST_AUTO_TEST_CASE(remove_invalid)
#     671                 :          2 : {
#     672                 :            :     // Confirm that invalid addresses are ignored in unserialization.
#     673                 :            : 
#     674                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     675                 :          2 :     CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
#     676                 :            : 
#     677                 :          2 :     const CAddress new1{ResolveService("5.5.5.5"), NODE_NONE};
#     678                 :          2 :     const CAddress new2{ResolveService("6.6.6.6"), NODE_NONE};
#     679                 :          2 :     const CAddress tried1{ResolveService("7.7.7.7"), NODE_NONE};
#     680                 :          2 :     const CAddress tried2{ResolveService("8.8.8.8"), NODE_NONE};
#     681                 :            : 
#     682                 :          2 :     addrman->Add({new1, tried1, new2, tried2}, CNetAddr{});
#     683                 :          2 :     addrman->Good(tried1);
#     684                 :          2 :     addrman->Good(tried2);
#     685                 :          2 :     BOOST_REQUIRE_EQUAL(addrman->size(), 4);
#     686                 :            : 
#     687                 :          2 :     stream << *addrman;
#     688                 :            : 
#     689                 :          2 :     const std::string str{stream.str()};
#     690                 :          2 :     size_t pos;
#     691                 :            : 
#     692                 :          2 :     const char new2_raw[]{6, 6, 6, 6};
#     693                 :          2 :     const uint8_t new2_raw_replacement[]{0, 0, 0, 0}; // 0.0.0.0 is !IsValid()
#     694                 :          2 :     pos = str.find(new2_raw, 0, sizeof(new2_raw));
#     695                 :          2 :     BOOST_REQUIRE(pos != std::string::npos);
#     696                 :          2 :     BOOST_REQUIRE(pos + sizeof(new2_raw_replacement) <= stream.size());
#     697                 :          2 :     memcpy(stream.data() + pos, new2_raw_replacement, sizeof(new2_raw_replacement));
#     698                 :            : 
#     699                 :          2 :     const char tried2_raw[]{8, 8, 8, 8};
#     700                 :          2 :     const uint8_t tried2_raw_replacement[]{255, 255, 255, 255}; // 255.255.255.255 is !IsValid()
#     701                 :          2 :     pos = str.find(tried2_raw, 0, sizeof(tried2_raw));
#     702                 :          2 :     BOOST_REQUIRE(pos != std::string::npos);
#     703                 :          2 :     BOOST_REQUIRE(pos + sizeof(tried2_raw_replacement) <= stream.size());
#     704                 :          2 :     memcpy(stream.data() + pos, tried2_raw_replacement, sizeof(tried2_raw_replacement));
#     705                 :            : 
#     706                 :          2 :     addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     707                 :          2 :     stream >> *addrman;
#     708                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 2);
#     709                 :          2 : }
#     710                 :            : 
#     711                 :            : BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
#     712                 :          2 : {
#     713                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     714                 :            : 
#     715                 :          2 :     BOOST_CHECK(addrman->size() == 0);
#     716                 :            : 
#     717                 :            :     // Empty addrman should return blank addrman info.
#     718                 :          2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
#     719                 :            : 
#     720                 :            :     // Add twenty two addresses.
#     721                 :          2 :     CNetAddr source = ResolveIP("252.2.2.2");
#     722         [ +  + ]:         46 :     for (unsigned int i = 1; i < 23; i++) {
#     723                 :         44 :         CService addr = ResolveService("250.1.1." + ToString(i));
#     724                 :         44 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
#     725                 :            : 
#     726                 :            :         // No collisions in tried.
#     727                 :         44 :         BOOST_CHECK(addrman->Good(addr));
#     728                 :         44 :         BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
#     729                 :         44 :     }
#     730                 :            : 
#     731                 :            :     // Ensure Good handles duplicates well.
#     732                 :            :     // If an address is a duplicate, Good will return false but will not count it as a collision.
#     733         [ +  + ]:         46 :     for (unsigned int i = 1; i < 23; i++) {
#     734                 :         44 :         CService addr = ResolveService("250.1.1." + ToString(i));
#     735                 :            : 
#     736                 :            :         // Unable to add duplicate address to tried table.
#     737                 :         44 :         BOOST_CHECK(!addrman->Good(addr));
#     738                 :            : 
#     739                 :            :         // Verify duplicate address not marked as a collision.
#     740                 :         44 :         BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
#     741                 :         44 :     }
#     742                 :          2 : }
#     743                 :            : 
#     744                 :            : BOOST_AUTO_TEST_CASE(addrman_noevict)
#     745                 :          2 : {
#     746                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     747                 :            : 
#     748                 :            :     // Add 35 addresses.
#     749                 :          2 :     CNetAddr source = ResolveIP("252.2.2.2");
#     750         [ +  + ]:         72 :     for (unsigned int i = 1; i < 36; i++) {
#     751                 :         70 :         CService addr = ResolveService("250.1.1." + ToString(i));
#     752                 :         70 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
#     753                 :            : 
#     754                 :            :         // No collision yet.
#     755                 :         70 :         BOOST_CHECK(addrman->Good(addr));
#     756                 :         70 :     }
#     757                 :            : 
#     758                 :            :     // Collision in tried table between 36 and 19.
#     759                 :          2 :     CService addr36 = ResolveService("250.1.1.36");
#     760                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr36, NODE_NONE)}, source));
#     761                 :          2 :     BOOST_CHECK(!addrman->Good(addr36));
#     762                 :          2 :     BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToString(), "250.1.1.19:0");
#     763                 :            : 
#     764                 :            :     // 36 should be discarded and 19 not evicted.
#     765                 :            :     // This means we keep 19 in the tried table and
#     766                 :            :     // 36 stays in the new table.
#     767                 :          2 :     addrman->ResolveCollisions();
#     768                 :          2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
#     769                 :            : 
#     770                 :            :     // Lets create two collisions.
#     771         [ +  + ]:         46 :     for (unsigned int i = 37; i < 59; i++) {
#     772                 :         44 :         CService addr = ResolveService("250.1.1." + ToString(i));
#     773                 :         44 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
#     774                 :         44 :         BOOST_CHECK(addrman->Good(addr));
#     775                 :         44 :     }
#     776                 :            : 
#     777                 :            :     // Cause a collision in the tried table.
#     778                 :          2 :     CService addr59 = ResolveService("250.1.1.59");
#     779                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr59, NODE_NONE)}, source));
#     780                 :          2 :     BOOST_CHECK(!addrman->Good(addr59));
#     781                 :            : 
#     782                 :          2 :     BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToString(), "250.1.1.10:0");
#     783                 :            : 
#     784                 :            :     // Cause a second collision in the new table.
#     785                 :          2 :     BOOST_CHECK(!addrman->Add({CAddress(addr36, NODE_NONE)}, source));
#     786                 :            : 
#     787                 :            :     // 36 still cannot be moved from new to tried due to colliding with 19
#     788                 :          2 :     BOOST_CHECK(!addrman->Good(addr36));
#     789                 :          2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() != "[::]:0");
#     790                 :            : 
#     791                 :            :     // Resolve all collisions.
#     792                 :          2 :     addrman->ResolveCollisions();
#     793                 :          2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
#     794                 :          2 : }
#     795                 :            : 
#     796                 :            : BOOST_AUTO_TEST_CASE(addrman_evictionworks)
#     797                 :          2 : {
#     798                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     799                 :            : 
#     800                 :          2 :     BOOST_CHECK(addrman->size() == 0);
#     801                 :            : 
#     802                 :            :     // Empty addrman should return blank addrman info.
#     803                 :          2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
#     804                 :            : 
#     805                 :            :     // Add 35 addresses
#     806                 :          2 :     CNetAddr source = ResolveIP("252.2.2.2");
#     807         [ +  + ]:         72 :     for (unsigned int i = 1; i < 36; i++) {
#     808                 :         70 :         CService addr = ResolveService("250.1.1." + ToString(i));
#     809                 :         70 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
#     810                 :            : 
#     811                 :            :         // No collision yet.
#     812                 :         70 :         BOOST_CHECK(addrman->Good(addr));
#     813                 :         70 :     }
#     814                 :            : 
#     815                 :            :     // Collision between 36 and 19.
#     816                 :          2 :     CService addr = ResolveService("250.1.1.36");
#     817                 :          2 :     BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
#     818                 :          2 :     BOOST_CHECK(!addrman->Good(addr));
#     819                 :            : 
#     820                 :          2 :     auto info = addrman->SelectTriedCollision().first;
#     821                 :          2 :     BOOST_CHECK_EQUAL(info.ToString(), "250.1.1.19:0");
#     822                 :            : 
#     823                 :            :     // Ensure test of address fails, so that it is evicted.
#     824                 :            :     // Update entry in tried by setting last good connection in the deep past.
#     825                 :          2 :     BOOST_CHECK(!addrman->Good(info, /*nTime=*/1));
#     826                 :          2 :     addrman->Attempt(info, /*fCountFailure=*/false, /*nTime=*/GetAdjustedTime() - 61);
#     827                 :            : 
#     828                 :            :     // Should swap 36 for 19.
#     829                 :          2 :     addrman->ResolveCollisions();
#     830                 :          2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
#     831                 :          2 :     AddressPosition addr_pos{addrman->FindAddressEntry(CAddress(addr, NODE_NONE)).value()};
#     832                 :          2 :     BOOST_CHECK(addr_pos.tried);
#     833                 :            : 
#     834                 :            :     // If 36 was swapped for 19, then adding 36 to tried should fail because we
#     835                 :            :     // are attempting to add a duplicate.
#     836                 :            :     // We check this by verifying Good() returns false and also verifying that
#     837                 :            :     // we have no collisions.
#     838                 :          2 :     BOOST_CHECK(!addrman->Good(addr));
#     839                 :          2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
#     840                 :            : 
#     841                 :            :     // 19 should fail as a collision (not a duplicate) if we now attempt to move
#     842                 :            :     // it to the tried table.
#     843                 :          2 :     CService addr19 = ResolveService("250.1.1.19");
#     844                 :          2 :     BOOST_CHECK(!addrman->Good(addr19));
#     845                 :          2 :     BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToString(), "250.1.1.36:0");
#     846                 :            : 
#     847                 :            :     // Eviction is also successful if too much time has passed since last try
#     848                 :          2 :     SetMockTime(GetTime() + 4 * 60 *60);
#     849                 :          2 :     addrman->ResolveCollisions();
#     850                 :          2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToString() == "[::]:0");
#     851                 :            :     //Now 19 is in tried again, and 36 back to new
#     852                 :          2 :     AddressPosition addr_pos19{addrman->FindAddressEntry(CAddress(addr19, NODE_NONE)).value()};
#     853                 :          2 :     BOOST_CHECK(addr_pos19.tried);
#     854                 :          2 :     AddressPosition addr_pos36{addrman->FindAddressEntry(CAddress(addr, NODE_NONE)).value()};
#     855                 :          2 :     BOOST_CHECK(!addr_pos36.tried);
#     856                 :          2 : }
#     857                 :            : 
#     858                 :            : static CDataStream AddrmanToStream(const AddrMan& addrman)
#     859                 :          4 : {
#     860                 :          4 :     CDataStream ssPeersIn(SER_DISK, CLIENT_VERSION);
#     861                 :          4 :     ssPeersIn << Params().MessageStart();
#     862                 :          4 :     ssPeersIn << addrman;
#     863                 :          4 :     return ssPeersIn;
#     864                 :          4 : }
#     865                 :            : 
#     866                 :            : BOOST_AUTO_TEST_CASE(load_addrman)
#     867                 :          2 : {
#     868                 :          2 :     AddrMan addrman{EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node)};
#     869                 :            : 
#     870                 :          2 :     CService addr1, addr2, addr3;
#     871                 :          2 :     BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false));
#     872                 :          2 :     BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false));
#     873                 :          2 :     BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false));
#     874                 :          2 :     BOOST_CHECK(Lookup("250.7.3.3"s, addr3, 9999, false));
#     875                 :          2 :     BOOST_CHECK(!Lookup("250.7.3.3\0example.com"s, addr3, 9999, false));
#     876                 :            : 
#     877                 :            :     // Add three addresses to new table.
#     878                 :          2 :     CService source;
#     879                 :          2 :     BOOST_CHECK(Lookup("252.5.1.1", source, 8333, false));
#     880                 :          2 :     std::vector<CAddress> addresses{CAddress(addr1, NODE_NONE), CAddress(addr2, NODE_NONE), CAddress(addr3, NODE_NONE)};
#     881                 :          2 :     BOOST_CHECK(addrman.Add(addresses, source));
#     882                 :          2 :     BOOST_CHECK(addrman.size() == 3);
#     883                 :            : 
#     884                 :            :     // Test that the de-serialization does not throw an exception.
#     885                 :          2 :     CDataStream ssPeers1 = AddrmanToStream(addrman);
#     886                 :          2 :     bool exceptionThrown = false;
#     887                 :          2 :     AddrMan addrman1{EMPTY_ASMAP, !DETERMINISTIC, GetCheckRatio(m_node)};
#     888                 :            : 
#     889                 :          2 :     BOOST_CHECK(addrman1.size() == 0);
#     890                 :          2 :     try {
#     891                 :          2 :         unsigned char pchMsgTmp[4];
#     892                 :          2 :         ssPeers1 >> pchMsgTmp;
#     893                 :          2 :         ssPeers1 >> addrman1;
#     894                 :          2 :     } catch (const std::exception&) {
#     895                 :          0 :         exceptionThrown = true;
#     896                 :          0 :     }
#     897                 :            : 
#     898                 :          2 :     BOOST_CHECK(addrman1.size() == 3);
#     899                 :          2 :     BOOST_CHECK(exceptionThrown == false);
#     900                 :            : 
#     901                 :            :     // Test that ReadFromStream creates an addrman with the correct number of addrs.
#     902                 :          2 :     CDataStream ssPeers2 = AddrmanToStream(addrman);
#     903                 :            : 
#     904                 :          2 :     AddrMan addrman2{EMPTY_ASMAP, !DETERMINISTIC, GetCheckRatio(m_node)};
#     905                 :          2 :     BOOST_CHECK(addrman2.size() == 0);
#     906                 :          2 :     ReadFromStream(addrman2, ssPeers2);
#     907                 :          2 :     BOOST_CHECK(addrman2.size() == 3);
#     908                 :          2 : }
#     909                 :            : 
#     910                 :            : // Produce a corrupt peers.dat that claims 20 addrs when it only has one addr.
#     911                 :            : static CDataStream MakeCorruptPeersDat()
#     912                 :          4 : {
#     913                 :          4 :     CDataStream s(SER_DISK, CLIENT_VERSION);
#     914                 :          4 :     s << ::Params().MessageStart();
#     915                 :            : 
#     916                 :          4 :     unsigned char nVersion = 1;
#     917                 :          4 :     s << nVersion;
#     918                 :          4 :     s << ((unsigned char)32);
#     919                 :          4 :     s << uint256::ONE;
#     920                 :          4 :     s << 10; // nNew
#     921                 :          4 :     s << 10; // nTried
#     922                 :            : 
#     923                 :          4 :     int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
#     924                 :          4 :     s << nUBuckets;
#     925                 :            : 
#     926                 :          4 :     CService serv;
#     927                 :          4 :     BOOST_CHECK(Lookup("252.1.1.1", serv, 7777, false));
#     928                 :          4 :     CAddress addr = CAddress(serv, NODE_NONE);
#     929                 :          4 :     CNetAddr resolved;
#     930                 :          4 :     BOOST_CHECK(LookupHost("252.2.2.2", resolved, false));
#     931                 :          4 :     AddrInfo info = AddrInfo(addr, resolved);
#     932                 :          4 :     s << info;
#     933                 :            : 
#     934                 :          4 :     return s;
#     935                 :          4 : }
#     936                 :            : 
#     937                 :            : BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
#     938                 :          2 : {
#     939                 :            :     // Test that the de-serialization of corrupted peers.dat throws an exception.
#     940                 :          2 :     CDataStream ssPeers1 = MakeCorruptPeersDat();
#     941                 :          2 :     bool exceptionThrown = false;
#     942                 :          2 :     AddrMan addrman1{EMPTY_ASMAP, !DETERMINISTIC, GetCheckRatio(m_node)};
#     943                 :          2 :     BOOST_CHECK(addrman1.size() == 0);
#     944                 :          2 :     try {
#     945                 :          2 :         unsigned char pchMsgTmp[4];
#     946                 :          2 :         ssPeers1 >> pchMsgTmp;
#     947                 :          2 :         ssPeers1 >> addrman1;
#     948                 :          2 :     } catch (const std::exception&) {
#     949                 :          2 :         exceptionThrown = true;
#     950                 :          2 :     }
#     951                 :            :     // Even though de-serialization failed addrman is not left in a clean state.
#     952                 :          2 :     BOOST_CHECK(addrman1.size() == 1);
#     953                 :          2 :     BOOST_CHECK(exceptionThrown);
#     954                 :            : 
#     955                 :            :     // Test that ReadFromStream fails if peers.dat is corrupt
#     956                 :          2 :     CDataStream ssPeers2 = MakeCorruptPeersDat();
#     957                 :            : 
#     958                 :          2 :     AddrMan addrman2{EMPTY_ASMAP, !DETERMINISTIC, GetCheckRatio(m_node)};
#     959                 :          2 :     BOOST_CHECK(addrman2.size() == 0);
#     960                 :          2 :     BOOST_CHECK_THROW(ReadFromStream(addrman2, ssPeers2), std::ios_base::failure);
#     961                 :          2 : }
#     962                 :            : 
#     963                 :            : BOOST_AUTO_TEST_CASE(addrman_update_address)
#     964                 :          2 : {
#     965                 :            :     // Tests updating nTime via Connected() and nServices via SetServices()
#     966                 :          2 :     auto addrman = std::make_unique<AddrMan>(EMPTY_ASMAP, DETERMINISTIC, GetCheckRatio(m_node));
#     967                 :          2 :     CNetAddr source{ResolveIP("252.2.2.2")};
#     968                 :          2 :     CAddress addr{CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE)};
#     969                 :            : 
#     970                 :          2 :     int64_t start_time{GetAdjustedTime() - 10000};
#     971                 :          2 :     addr.nTime = start_time;
#     972                 :          2 :     BOOST_CHECK(addrman->Add({addr}, source));
#     973                 :          2 :     BOOST_CHECK_EQUAL(addrman->size(), 1U);
#     974                 :            : 
#     975                 :            :     // Updating an addrman entry with a different port doesn't change it
#     976                 :          2 :     CAddress addr_diff_port{CAddress(ResolveService("250.1.1.1", 8334), NODE_NONE)};
#     977                 :          2 :     addr_diff_port.nTime = start_time;
#     978                 :          2 :     addrman->Connected(addr_diff_port);
#     979                 :          2 :     addrman->SetServices(addr_diff_port, NODE_NETWORK_LIMITED);
#     980                 :          2 :     std::vector<CAddress> vAddr1{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
#     981                 :          2 :     BOOST_CHECK_EQUAL(vAddr1.size(), 1U);
#     982                 :          2 :     BOOST_CHECK_EQUAL(vAddr1.at(0).nTime, start_time);
#     983                 :          2 :     BOOST_CHECK_EQUAL(vAddr1.at(0).nServices, NODE_NONE);
#     984                 :            : 
#     985                 :            :     // Updating an addrman entry with the correct port is successful
#     986                 :          2 :     addrman->Connected(addr);
#     987                 :          2 :     addrman->SetServices(addr, NODE_NETWORK_LIMITED);
#     988                 :          2 :     std::vector<CAddress> vAddr2 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
#     989                 :          2 :     BOOST_CHECK_EQUAL(vAddr2.size(), 1U);
#     990                 :          2 :     BOOST_CHECK(vAddr2.at(0).nTime >= start_time + 10000);
#     991                 :          2 :     BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);
#     992                 :          2 : }
#     993                 :            : 
#     994                 :            : BOOST_AUTO_TEST_SUITE_END()

Generated by: LCOV version 0-eol-96201-ge66f56f4af6a