LCOV - code coverage report
Current view: top level - src/test - addrman_tests.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 99.9 % 805 804
Test Date: 2026-10-31 06:23:51 Functions: 100.0 % 59 59
Branches: 50.5 % 5256 2654

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2012-present 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 <netgroup.h>
      13                 :             : #include <random.h>
      14                 :             : #include <test/data/asmap.raw.h>
      15                 :             : #include <test/util/common.h>
      16                 :             : #include <test/util/setup_common.h>
      17                 :             : #include <test/util/time.h>
      18                 :             : #include <util/asmap.h>
      19                 :             : #include <util/string.h>
      20                 :             : 
      21                 :             : #include <boost/test/unit_test.hpp>
      22                 :             : 
      23                 :             : #include <algorithm>
      24                 :             : #include <cstdint>
      25                 :             : #include <optional>
      26                 :             : #include <string>
      27                 :             : #include <unordered_set>
      28                 :             : #include <utility>
      29                 :             : #include <vector>
      30                 :             : 
      31                 :             : using namespace std::literals;
      32                 :             : using node::NodeContext;
      33                 :             : using util::ToString;
      34                 :             : 
      35                 :             : static auto EMPTY_NETGROUPMAN{NetGroupManager::NoAsmap()};
      36                 :             : static const bool DETERMINISTIC{true};
      37                 :             : 
      38                 :          27 : static int32_t GetCheckRatio(const NodeContext& node_ctx)
      39                 :             : {
      40         [ +  - ]:          81 :     return std::clamp<int32_t>(node_ctx.args->GetIntArg("-checkaddrman", 100), 0, 1000000);
      41                 :             : }
      42                 :             : 
      43                 :        6823 : static CNetAddr ResolveIP(const std::string& ip)
      44                 :             : {
      45         [ +  - ]:        6823 :     const std::optional<CNetAddr> addr{LookupHost(ip, false)};
      46   [ +  -  +  -  :       13646 :     BOOST_CHECK_MESSAGE(addr.has_value(), strprintf("failed to resolve: %s", ip));
                   +  - ]
      47         [ +  - ]:        6823 :     return addr.value_or(CNetAddr{});
      48                 :        6823 : }
      49                 :             : 
      50                 :        6639 : static CService ResolveService(const std::string& ip, uint16_t port = 0)
      51                 :             : {
      52         [ +  - ]:        6639 :     const std::optional<CService> serv{Lookup(ip, port, false)};
      53   [ +  -  +  -  :       13278 :     BOOST_CHECK_MESSAGE(serv.has_value(), strprintf("failed to resolve: %s:%i", ip, port));
                   +  - ]
      54         [ +  - ]:        6639 :     return serv.value_or(CService{});
      55                 :        6639 : }
      56                 :             : 
      57                 :             : BOOST_FIXTURE_TEST_SUITE(addrman_tests, BasicTestingSetup)
      58                 :             : 
      59   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_simple)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
      60                 :             : {
      61                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
      62                 :             : 
      63   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
      64                 :             : 
      65                 :             :     // Test: Does Addrman respond correctly when empty.
      66   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 0U);
                   +  - ]
      67         [ +  - ]:           1 :     auto addr_null = addrman->Select().first;
      68   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addr_null.ToStringAddrPort(), "[::]:0");
                   +  - ]
      69                 :             : 
      70                 :             :     // Test: Does Addrman::Add work as expected.
      71   [ +  -  +  - ]:           1 :     CService addr1 = ResolveService("250.1.1.1", 8333);
      72   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
      73   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 1U);
                   +  - ]
      74         [ +  - ]:           1 :     auto addr_ret1 = addrman->Select().first;
      75   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addr_ret1.ToStringAddrPort(), "250.1.1.1:8333");
                   +  - ]
      76                 :             : 
      77                 :             :     // Test: Does IP address deduplication work correctly.
      78                 :             :     //  Expected dup IP should not be added.
      79   [ +  -  +  - ]:           1 :     CService addr1_dup = ResolveService("250.1.1.1", 8333);
      80   [ +  -  +  -  :           5 :     BOOST_CHECK(!addrman->Add({CAddress(addr1_dup, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
      81   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 1U);
                   +  - ]
      82                 :             : 
      83                 :             : 
      84                 :             :     // Test: New table has one addr and we add a diff addr we should
      85                 :             :     //  have at least one addr.
      86                 :             :     // Note that addrman's size cannot be tested reliably after insertion, as
      87                 :             :     // hash collisions may occur. But we can always be sure of at least one
      88                 :             :     // success.
      89                 :             : 
      90   [ +  -  +  - ]:           1 :     CService addr2 = ResolveService("250.1.1.2", 8333);
      91   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
      92   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Size() >= 1);
             +  -  +  - ]
      93                 :             : 
      94                 :             :     // Test: reset addrman and test AddrMan::Add multiple addresses works as expected
      95   [ +  -  +  - ]:           2 :     addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
      96                 :           1 :     std::vector<CAddress> vAddr;
      97   [ +  -  +  -  :           2 :     vAddr.emplace_back(ResolveService("250.1.1.3", 8333), NODE_NONE);
                   +  - ]
      98   [ +  -  +  -  :           2 :     vAddr.emplace_back(ResolveService("250.1.1.4", 8333), NODE_NONE);
                   +  - ]
      99   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Add(vAddr, source));
             +  -  +  - ]
     100   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Size() >= 1);
                   +  - ]
     101   [ +  -  +  -  :           7 : }
                   +  - ]
     102                 :             : 
     103                 :             : 
     104   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_terrible_many_failures)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     105                 :             : {
     106                 :           1 :     FakeNodeClock clock{};
     107                 :             : 
     108   [ +  -  +  - ]:           1 :     auto addrman{std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node))};
     109                 :             : 
     110   [ +  -  +  - ]:           1 :     CNetAddr source{ResolveIP("250.1.2.1")};
     111   [ +  -  +  - ]:           2 :     CAddress addr{CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE)};
     112                 :           1 :     addr.nTime = Now<NodeSeconds>();
     113                 :             : 
     114   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({addr}, source));
          +  -  +  -  +  
                +  -  - ]
     115   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(addr));
             +  -  +  - ]
     116                 :             : 
     117         [ +  - ]:           1 :     clock += ADDRMAN_MIN_FAIL + 24h;
     118                 :             : 
     119   [ +  -  +  - ]:           2 :     CAddress addr_helper{CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE)};
     120                 :           1 :     addr_helper.nTime = Now<NodeSeconds>();
     121   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({addr_helper}, source));
          +  -  +  -  +  
                +  -  - ]
     122   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(addr_helper));
                   +  - ]
     123                 :             : 
     124         [ +  + ]:          11 :     for (int i = 0; i < ADDRMAN_MAX_FAILURES; ++i) {
     125                 :             :         // Use a time > 60s ago so IsTerrible doesn't bail out at the "tried in the last minute" check
     126         [ +  - ]:          10 :         addrman->Attempt(addr, /*fCountFailure=*/true, Now<NodeSeconds>() - 61s);
     127                 :             :     }
     128                 :             : 
     129         [ +  - ]:           1 :     std::vector<CAddress> filtered{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
     130   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(filtered.size(), 1U);
                   +  - ]
     131   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(filtered[0].ToStringAddrPort(), "251.252.2.3:8333");
                   +  - ]
     132                 :             : 
     133         [ +  - ]:           1 :     std::vector<CAddress> unfiltered{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt, /*filtered=*/false)};
     134   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(unfiltered.size(), 2U);
                   +  - ]
     135                 :           3 : }
     136                 :             : 
     137                 :             : 
     138   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_penalty_self_announcement)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     139                 :             : {
     140                 :           1 :     FakeNodeClock clock{};
     141   [ +  -  +  - ]:           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     142                 :             : 
     143                 :           1 :     const auto base_time{Now<NodeSeconds>() - 10000s};
     144   [ +  -  +  - ]:           1 :     CService addr1 = ResolveService("250.1.1.1", 8333);
     145   [ +  -  +  - ]:           1 :     CNetAddr source1 = ResolveIP("250.1.1.1"); // Same as addr1 - self announcement
     146                 :             : 
     147                 :           1 :     CAddress caddr1(addr1, NODE_NONE);
     148                 :           1 :     caddr1.nTime = base_time;
     149                 :             : 
     150                 :           1 :     const auto time_penalty{3600s};
     151                 :             : 
     152   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({caddr1}, source1, time_penalty));
          +  -  +  -  +  
                +  -  - ]
     153                 :             : 
     154         [ +  - ]:           1 :     auto addr_pos1{addrman->FindAddressEntry(caddr1)};
     155   [ +  -  +  -  :           2 :     BOOST_REQUIRE(addr_pos1.has_value());
                   +  - ]
     156                 :             : 
     157         [ +  - ]:           1 :     std::vector<CAddress> addresses{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
     158   [ +  -  -  +  :           1 :     BOOST_REQUIRE_EQUAL(addresses.size(), 1U);
                   +  - ]
     159                 :             : 
     160   [ +  -  +  -  :           2 :     BOOST_CHECK(addresses[0].nTime == base_time);
                   +  - ]
     161                 :             : 
     162   [ +  -  +  - ]:           1 :     CService addr2{ResolveService("250.1.1.2", 8333)};
     163   [ +  -  +  - ]:           1 :     CNetAddr source2{ResolveIP("250.1.1.3")}; // Different from addr2 - not self announcement
     164                 :             : 
     165                 :           1 :     CAddress caddr2(addr2, NODE_NONE);
     166                 :           1 :     caddr2.nTime = base_time;
     167                 :             : 
     168   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({caddr2}, source2, time_penalty));
          +  -  +  -  +  
                +  -  - ]
     169                 :             : 
     170         [ +  - ]:           2 :     addresses = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
     171   [ +  -  -  +  :           1 :     BOOST_REQUIRE_EQUAL(addresses.size(), 2U);
                   +  - ]
     172                 :             : 
     173                 :           1 :     CAddress retrieved_addr2{addresses[0]};
     174   [ +  -  +  - ]:           2 :     BOOST_CHECK(retrieved_addr2.nTime == base_time - time_penalty);
     175                 :           3 : }
     176                 :             : 
     177   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_ports)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     178                 :             : {
     179                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     180                 :             : 
     181   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
     182                 :             : 
     183   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 0U);
                   +  - ]
     184                 :             : 
     185                 :             :     // Test 7; Addr with same IP but diff port does not replace existing addr.
     186   [ +  -  +  - ]:           1 :     CService addr1 = ResolveService("250.1.1.1", 8333);
     187   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     188   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 1U);
                   +  - ]
     189                 :             : 
     190   [ +  -  +  - ]:           1 :     CService addr1_port = ResolveService("250.1.1.1", 8334);
     191   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr1_port, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     192   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 2U);
                   +  - ]
     193         [ +  - ]:           1 :     auto addr_ret2 = addrman->Select().first;
     194   [ +  -  +  -  :           5 :     BOOST_CHECK(addr_ret2.ToStringAddrPort() == "250.1.1.1:8333" || addr_ret2.ToStringAddrPort() == "250.1.1.1:8334");
          +  -  +  -  +  
          -  +  -  +  -  
             -  -  -  - ]
     195                 :             : 
     196                 :             :     // Test: Add same IP but diff port to tried table; this converts the entry with
     197                 :             :     // the specified port to tried, but not the other.
     198         [ +  - ]:           2 :     addrman->Good(CAddress(addr1_port, NODE_NONE));
     199   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 2U);
                   +  - ]
     200                 :           1 :     bool new_only = true;
     201         [ +  - ]:           1 :     auto addr_ret3 = addrman->Select(new_only).first;
     202   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addr_ret3.ToStringAddrPort(), "250.1.1.1:8333");
                   +  - ]
     203   [ +  -  +  - ]:           5 : }
     204                 :             : 
     205   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_select)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     206                 :             : {
     207                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     208   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Select(false).first.IsValid());
          +  -  +  -  +  
                      - ]
     209   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Select(true).first.IsValid());
          +  -  +  -  +  
                      - ]
     210                 :             : 
     211   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
     212                 :             : 
     213                 :             :     // Add 1 address to the new table
     214   [ +  -  +  - ]:           1 :     CService addr1 = ResolveService("250.1.1.1", 8333);
     215   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     216   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 1U);
                   +  - ]
     217                 :             : 
     218   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Select(/*new_only=*/true).first == addr1);
          +  -  +  -  +  
                      - ]
     219   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Select(/*new_only=*/false).first == addr1);
          +  -  +  -  +  
                      - ]
     220                 :             : 
     221                 :             :     // Move address to the tried table
     222   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));
             +  -  +  - ]
     223                 :             : 
     224   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 1U);
                   +  - ]
     225   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Select(/*new_only=*/true).first.IsValid());
          +  -  +  -  +  
                      - ]
     226   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Select().first == addr1);
          +  -  +  -  +  
                      - ]
     227   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 1U);
                   +  - ]
     228                 :             : 
     229                 :             :     // Add one address to the new table
     230   [ +  -  +  - ]:           1 :     CService addr2 = ResolveService("250.3.1.1", 8333);
     231   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, addr2));
          +  -  +  +  +  
                -  -  - ]
     232   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Select(/*new_only=*/true).first == addr2);
          +  -  +  -  +  
                      - ]
     233                 :             : 
     234                 :             :     // Add two more addresses to the new table
     235   [ +  -  +  - ]:           1 :     CService addr3 = ResolveService("250.3.2.2", 9999);
     236   [ +  -  +  - ]:           1 :     CService addr4 = ResolveService("250.3.3.3", 9999);
     237                 :             : 
     238   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr3, NODE_NONE)}, addr2));
          +  -  +  +  +  
                -  -  - ]
     239   [ +  -  +  -  :           6 :     BOOST_CHECK(addrman->Add({CAddress(addr4, NODE_NONE)}, ResolveService("250.4.1.1", 8333)));
          +  -  +  -  +  
          -  +  +  +  -  
                   -  - ]
     240                 :             : 
     241                 :             :     // Add three addresses to tried table.
     242   [ +  -  +  - ]:           1 :     CService addr5 = ResolveService("250.4.4.4", 8333);
     243   [ +  -  +  - ]:           1 :     CService addr6 = ResolveService("250.4.5.5", 7777);
     244   [ +  -  +  - ]:           1 :     CService addr7 = ResolveService("250.4.6.6", 8333);
     245                 :             : 
     246   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr5, NODE_NONE)}, addr3));
          +  -  +  +  +  
                -  -  - ]
     247   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(CAddress(addr5, NODE_NONE)));
             +  -  +  - ]
     248   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr6, NODE_NONE)}, addr3));
          +  -  +  +  +  
                -  -  - ]
     249   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(CAddress(addr6, NODE_NONE)));
             +  -  +  - ]
     250   [ +  -  +  -  :           6 :     BOOST_CHECK(addrman->Add({CAddress(addr7, NODE_NONE)}, ResolveService("250.1.1.3", 8333)));
          +  -  +  -  +  
          -  +  +  +  -  
                   -  - ]
     251   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(CAddress(addr7, NODE_NONE)));
             +  -  +  - ]
     252                 :             : 
     253                 :             :     // 6 addrs + 1 addr from last test = 7.
     254   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 7U);
                   +  - ]
     255                 :             : 
     256                 :             :     // Select pulls from new and tried regardless of port number.
     257                 :           1 :     std::set<uint16_t> ports;
     258         [ +  + ]:          21 :     for (int i = 0; i < 20; ++i) {
     259   [ +  -  +  -  :          40 :         ports.insert(addrman->Select().first.GetPort());
                   +  - ]
     260                 :             :     }
     261   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(ports.size(), 3U);
     262   [ +  -  +  -  :          15 : }
          +  -  +  -  +  
             -  +  -  +  
                      - ]
     263                 :             : 
     264   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_select_by_network)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     265                 :             : {
     266                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     267   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/true, {NET_IPV4}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     268   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_IPV4}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     269                 :             : 
     270                 :             :     // add ipv4 address to the new table
     271   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
     272   [ +  -  +  - ]:           1 :     CService addr1 = ResolveService("250.1.1.1", 8333);
     273   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     274                 :             : 
     275   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Select(/*new_only=*/true, {NET_IPV4}).first == addr1);
          +  -  +  -  +  
                -  +  - ]
     276   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_IPV4}).first == addr1);
          +  -  +  -  +  
                -  +  - ]
     277   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_IPV6}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     278   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_ONION}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     279   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_I2P}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     280   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_CJDNS}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     281   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/true, {NET_CJDNS}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     282   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Select(/*new_only=*/false).first == addr1);
          +  -  +  -  +  
                      - ]
     283                 :             : 
     284                 :             :     // add I2P address to the new table
     285         [ +  - ]:           1 :     CAddress i2p_addr;
     286         [ +  - ]:           1 :     i2p_addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");
     287   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({i2p_addr}, source));
          +  -  +  -  +  
                +  -  - ]
     288                 :             : 
     289   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Select(/*new_only=*/true, {NET_I2P}).first == i2p_addr);
          +  -  +  -  +  
                -  +  - ]
     290   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_I2P}).first == i2p_addr);
          +  -  +  -  +  
                -  +  - ]
     291   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_IPV4}).first == addr1);
          +  -  +  -  +  
                -  +  - ]
     292   [ +  -  +  - ]:           2 :     std::unordered_set<Network> nets_with_entries = {NET_IPV4, NET_I2P};
     293   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Select(/*new_only=*/false, nets_with_entries).first.IsValid());
          +  -  +  -  +  
                      - ]
     294   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_IPV6}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     295   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_ONION}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     296   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/false, {NET_CJDNS}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     297   [ +  -  +  - ]:           2 :     std::unordered_set<Network> nets_without_entries = {NET_IPV6, NET_ONION, NET_CJDNS};
     298   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Select(/*new_only=*/false, nets_without_entries).first.IsValid());
          +  -  +  -  +  
                      - ]
     299                 :             : 
     300                 :             :     // bump I2P address to tried table
     301   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(i2p_addr));
             +  -  +  - ]
     302                 :             : 
     303   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Select(/*new_only=*/true, {NET_I2P}).first.IsValid());
          +  -  +  -  +  
                -  +  - ]
     304   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_I2P}).first == i2p_addr);
          +  -  +  -  +  
                -  +  - ]
     305                 :             : 
     306                 :             :     // add another I2P address to the new table
     307         [ +  - ]:           1 :     CAddress i2p_addr2;
     308         [ +  - ]:           1 :     i2p_addr2.SetSpecial("c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p");
     309   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({i2p_addr2}, source));
          +  -  +  -  +  
                +  -  - ]
     310                 :             : 
     311   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Select(/*new_only=*/true, {NET_I2P}).first == i2p_addr2);
          +  -  +  -  +  
                      - ]
     312                 :             : 
     313                 :             :     // ensure that both new and tried table are selected from
     314                 :           1 :     bool new_selected{false};
     315                 :           1 :     bool tried_selected{false};
     316                 :           1 :     int counter = 256;
     317                 :             : 
     318   [ +  -  +  + ]:           3 :     while (--counter > 0 && (!new_selected || !tried_selected)) {
     319   [ +  -  +  -  :           4 :         const CAddress selected{addrman->Select(/*new_only=*/false, {NET_I2P}).first};
                   +  - ]
     320   [ +  -  +  -  :           5 :         BOOST_REQUIRE(selected == i2p_addr || selected == i2p_addr2);
          +  +  +  -  +  
             -  +  -  +  
                      - ]
     321   [ +  -  +  + ]:           2 :         if (selected == i2p_addr) {
     322                 :             :             tried_selected = true;
     323                 :             :         } else {
     324                 :           1 :             new_selected = true;
     325                 :             :         }
     326                 :           2 :     }
     327                 :             : 
     328   [ +  -  +  -  :           2 :     BOOST_CHECK(new_selected);
                   +  - ]
     329   [ +  -  +  - ]:           2 :     BOOST_CHECK(tried_selected);
     330         [ +  - ]:           5 : }
     331                 :             : 
     332   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_select_uniform_in_bucket)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     333                 :             : {
     334                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     335   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
     336                 :             : 
     337                 :             :     // With the deterministic key, these addresses all end up in new bucket 224, at the listed
     338                 :             :     // positions. Picking the first entry found when scanning from a random position would
     339                 :             :     // strongly favor entries following a gap: in each of the cases tested below, one entry
     340                 :             :     // would be selected 61/64 or 63/64 of the time.
     341                 :           1 :     const std::vector<std::pair<CService, int>> entries{
     342   [ +  -  +  -  :           2 :         {ResolveService("250.33.1.1", 8333), 0},
                   +  - ]
     343   [ +  -  +  - ]:           2 :         {ResolveService("250.53.1.1", 8333), 1},
     344   [ +  -  +  - ]:           2 :         {ResolveService("2a01:e::1", 8333), 62},
     345   [ +  -  +  - ]:           2 :         {ResolveService("2a01:a0::1", 8333), 63},
     346   [ +  +  -  - ]:           5 :     };
     347   [ +  -  +  + ]:           5 :     for (const auto& [addr, position] : entries) {
     348   [ +  -  +  -  :          20 :         BOOST_REQUIRE(addrman->Add({CAddress(addr, NODE_NONE)}, source));
          +  -  +  +  -  
                      - ]
     349         [ +  - ]:           8 :         const auto addr_pos{addrman->FindAddressEntry(CAddress(addr, NODE_NONE))};
     350   [ +  -  +  -  :           8 :         BOOST_REQUIRE(addr_pos.has_value());
                   +  - ]
     351   [ +  -  +  -  :           8 :         BOOST_REQUIRE(!addr_pos->tried);
                   +  - ]
     352   [ +  -  +  - ]:           4 :         BOOST_REQUIRE_EQUAL(addr_pos->bucket, 224);
     353   [ +  -  +  - ]:           4 :         BOOST_REQUIRE_EQUAL(addr_pos->position, position);
     354                 :             :     }
     355                 :             : 
     356                 :             :     // Verify that Select() only returns entries matching networks, and picks each of them
     357                 :             :     // equally often.
     358                 :           4 :     const auto check_uniform = [&](const std::unordered_set<Network>& networks) {
     359                 :           3 :         std::vector<CService> matching;
     360   [ +  +  +  + ]:          15 :         for (const auto& [addr, position] : entries) {
     361   [ +  +  +  -  :          12 :             if (networks.empty() || networks.contains(addr.GetNetwork())) matching.push_back(addr);
             +  +  +  - ]
     362                 :             :         }
     363                 :           3 :         constexpr int SAMPLES{600};
     364   [ -  +  +  - ]:           3 :         std::vector<int> counts(matching.size());
     365         [ +  + ]:        1803 :         for (int i = 0; i < SAMPLES; ++i) {
     366         [ +  - ]:        1800 :             const CService selected{addrman->Select(/*new_only=*/false, networks).first};
     367         [ +  - ]:        1800 :             const auto it{std::find(matching.begin(), matching.end(), selected)};
     368   [ +  -  +  - ]:        3600 :             BOOST_REQUIRE(it != matching.end());
     369                 :        1800 :             ++counts[it - matching.begin()];
     370                 :        1800 :         }
     371                 :             :         // Compare the counts with a uniform distribution using a chi-square test. The critical
     372                 :             :         // values correspond to a false positive probability of 1e-9, for 1 and 3 degrees of
     373                 :             :         // freedom (2 and 4 matching entries) respectively.
     374   [ +  -  -  +  :           7 :         BOOST_REQUIRE(matching.size() == 2 || matching.size() == 4);
          +  +  +  -  +  
                -  -  + ]
     375   [ -  +  +  + ]:           3 :         const double chi_square_critical{matching.size() == 2 ? 37.32 : 44.84};
     376                 :           3 :         const double expected_count{double(SAMPLES) / matching.size()};
     377                 :           3 :         double chi_square{0.0};
     378         [ +  + ]:          11 :         for (int count : counts) {
     379                 :           8 :             chi_square += (count - expected_count) * (count - expected_count) / expected_count;
     380                 :             :         }
     381   [ +  -  +  - ]:           3 :         BOOST_CHECK_LT(chi_square, chi_square_critical);
     382                 :           4 :     };
     383         [ +  - ]:           1 :     check_uniform({});
     384   [ +  -  +  -  :           3 :     check_uniform({NET_IPV4});
                   +  - ]
     385   [ +  -  +  - ]:           3 :     check_uniform({NET_IPV6});
     386   [ +  -  +  -  :          13 : }
          +  -  +  -  +  
                -  -  - ]
     387                 :             : 
     388   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_select_special)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     389                 :             : {
     390                 :             :     // use a non-deterministic addrman to ensure a passing test isn't due to setup
     391                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, /*deterministic=*/false, GetCheckRatio(m_node));
     392                 :             : 
     393   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
     394                 :             : 
     395                 :             :     // add I2P address to the tried table
     396         [ +  - ]:           1 :     CAddress i2p_addr;
     397         [ +  - ]:           1 :     i2p_addr.SetSpecial("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p");
     398   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({i2p_addr}, source));
          +  -  +  -  +  
                +  -  - ]
     399   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(i2p_addr));
             +  -  +  - ]
     400                 :             : 
     401                 :             :     // add ipv4 address to the new table
     402   [ +  -  +  - ]:           1 :     CService addr1 = ResolveService("250.1.1.3", 8333);
     403   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     404                 :             : 
     405                 :             :     // since the only ipv4 address is on the new table, ensure that the new
     406                 :             :     // table gets selected even if new_only is false. if the table was being
     407                 :             :     // selected at random, this test will sporadically fail
     408   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Select(/*new_only=*/false, {NET_IPV4}).first == addr1);
          +  -  +  -  +  
                      - ]
     409         [ +  - ]:           4 : }
     410                 :             : 
     411   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_new_collisions)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     412                 :             : {
     413                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     414                 :             : 
     415   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
     416                 :             : 
     417                 :           1 :     uint32_t num_addrs{0};
     418                 :             : 
     419   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
                   +  - ]
     420                 :             : 
     421         [ +  + ]:          23 :     while (num_addrs < 22) { // Magic number! 250.1.1.1 - 250.1.1.22 do not collide with deterministic key = 1
     422   [ +  -  +  -  :          44 :         CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
                   +  - ]
     423   [ +  -  +  -  :         110 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     424                 :             : 
     425                 :             :         // Test: No collision in new table yet.
     426   [ +  -  +  -  :          22 :         BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
                   +  - ]
     427                 :          22 :     }
     428                 :             : 
     429                 :             :     // Test: new table collision!
     430   [ +  -  +  -  :           2 :     CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
                   +  - ]
     431                 :           1 :     uint32_t collisions{1};
     432   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     433   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
                   +  - ]
     434                 :             : 
     435   [ +  -  +  -  :           2 :     CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
                   +  - ]
     436   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     437   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), num_addrs - collisions);
                   +  - ]
     438   [ +  -  +  -  :          49 : }
                   +  - ]
     439                 :             : 
     440   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_new_multiplicity)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     441                 :             : {
     442                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     443   [ +  -  +  - ]:           2 :     CAddress addr{CAddress(ResolveService("253.3.3.3", 8333), NODE_NONE)};
     444                 :           1 :     const auto start_time{Now<NodeSeconds>()};
     445                 :           1 :     addr.nTime = start_time;
     446                 :             : 
     447                 :             :     // test that multiplicity stays at 1 if nTime doesn't increase
     448         [ +  + ]:          20 :     for (unsigned int i = 1; i < 20; ++i) {
     449   [ +  -  +  -  :          57 :         std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};
                   +  - ]
     450         [ +  - ]:          19 :         CNetAddr source{ResolveIP(addr_ip)};
     451   [ +  -  +  -  :          38 :         addrman->Add({addr}, source);
             +  +  -  - ]
     452                 :          19 :     }
     453         [ +  - ]:           1 :     AddressPosition addr_pos = addrman->FindAddressEntry(addr).value();
     454   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(addr_pos.multiplicity, 1U);
     455   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 1U);
                   +  - ]
     456                 :             : 
     457                 :             :     // if nTime increases, an addr can occur in up to 8 buckets
     458                 :             :     // The acceptance probability decreases exponentially with existing multiplicity -
     459                 :             :     // choose number of iterations such that it gets to 8 with deterministic addrman.
     460         [ +  + ]:         400 :     for (unsigned int i = 1; i < 400; ++i) {
     461   [ +  -  +  -  :        1197 :         std::string addr_ip{ToString(i % 256) + "." + ToString(i >> 8 % 256) + ".1.1"};
                   +  - ]
     462         [ +  - ]:         399 :         CNetAddr source{ResolveIP(addr_ip)};
     463                 :         399 :         addr.nTime = start_time + std::chrono::seconds{i};
     464   [ +  -  +  -  :         798 :         addrman->Add({addr}, source);
             +  +  -  - ]
     465                 :         399 :     }
     466         [ +  - ]:           1 :     AddressPosition addr_pos_multi = addrman->FindAddressEntry(addr).value();
     467   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(addr_pos_multi.multiplicity, 8U);
     468                 :             :     // multiplicity doesn't affect size
     469   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 1U);
                   +  - ]
     470                 :         419 : }
     471                 :             : 
     472   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     473                 :             : {
     474                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     475                 :             : 
     476   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
     477                 :             : 
     478                 :           1 :     uint32_t num_addrs{0};
     479                 :             : 
     480   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), num_addrs);
                   +  - ]
     481                 :             : 
     482         [ +  + ]:          36 :     while (num_addrs < 35) { // Magic number! 250.1.1.1 - 250.1.1.35 do not collide in tried with deterministic key = 1
     483   [ +  -  +  -  :          70 :         CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
                   +  - ]
     484   [ +  -  +  -  :         175 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     485                 :             : 
     486                 :             :         // Test: Add to tried without collision
     487   [ +  -  +  -  :          70 :         BOOST_CHECK(addrman->Good(CAddress(addr, NODE_NONE)));
                   +  - ]
     488                 :             : 
     489                 :          35 :     }
     490                 :             : 
     491                 :             :     // Test: Unable to add to tried table due to collision!
     492   [ +  -  +  -  :           2 :     CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
                   +  - ]
     493   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     494   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Good(CAddress(addr1, NODE_NONE)));
             +  -  +  - ]
     495                 :             : 
     496                 :             :     // Test: Add the next address to tried without collision
     497   [ +  -  +  -  :           2 :     CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
                   +  - ]
     498   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     499   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(CAddress(addr2, NODE_NONE)));
                   +  - ]
     500   [ +  -  +  -  :          75 : }
                   +  - ]
     501                 :             : 
     502                 :             : 
     503   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_getaddr)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     504                 :             : {
     505                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     506                 :             : 
     507                 :             :     // Test: Sanity check, GetAddr should never return anything if addrman
     508                 :             :     //  is empty.
     509   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 0U);
                   +  - ]
     510         [ +  - ]:           1 :     std::vector<CAddress> vAddr1 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
     511   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
                   +  - ]
     512                 :             : 
     513   [ +  -  +  - ]:           2 :     CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
     514                 :           1 :     addr1.nTime = Now<NodeSeconds>(); // Set time so isTerrible = false
     515   [ +  -  +  - ]:           2 :     CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
     516                 :           1 :     addr2.nTime = Now<NodeSeconds>();
     517   [ +  -  +  - ]:           2 :     CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
     518                 :           1 :     addr3.nTime = Now<NodeSeconds>();
     519   [ +  -  +  - ]:           2 :     CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
     520                 :           1 :     addr4.nTime = Now<NodeSeconds>();
     521   [ +  -  +  - ]:           2 :     CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
     522                 :           1 :     addr5.nTime = Now<NodeSeconds>();
     523   [ +  -  +  - ]:           1 :     CNetAddr source1 = ResolveIP("250.1.2.1");
     524   [ +  -  +  - ]:           1 :     CNetAddr source2 = ResolveIP("250.2.3.3");
     525                 :             : 
     526                 :             :     // Test: Ensure GetAddr works with new addresses.
     527   [ +  -  +  -  :           6 :     BOOST_CHECK(addrman->Add({addr1, addr3, addr5}, source1));
          +  -  +  -  +  
                +  -  - ]
     528   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({addr2, addr4}, source2));
          +  -  +  -  +  
                +  -  - ]
     529                 :             : 
     530   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 5U);
                   +  - ]
     531                 :             :     // Net processing asks for 23% of addresses. 23% of 5 is 1 rounded down.
     532   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt).size(), 1U);
                   +  - ]
     533                 :             : 
     534                 :             :     // Test: Ensure GetAddr works with new and tried addresses.
     535   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(CAddress(addr1, NODE_NONE)));
             +  -  +  - ]
     536   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(CAddress(addr2, NODE_NONE)));
             +  -  +  - ]
     537   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 5U);
                   +  - ]
     538   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt).size(), 1U);
                   +  - ]
     539                 :             : 
     540                 :             :     // Test: Ensure GetAddr still returns 23% when addrman has many addrs.
     541         [ +  + ]:        2048 :     for (unsigned int i = 1; i < (8 * 256); i++) {
     542                 :        2047 :         int octet1 = i % 256;
     543                 :        2047 :         int octet2 = i >> 8 % 256;
     544   [ +  -  +  -  :        6141 :         std::string strAddr = ToString(octet1) + "." + ToString(octet2) + ".1.23";
                   +  - ]
     545         [ +  - ]:        4094 :         CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
     546                 :             : 
     547                 :             :         // Ensure that for all addrs in addrman, isTerrible == false.
     548                 :        2047 :         addr.nTime = Now<NodeSeconds>();
     549   [ +  -  +  -  :        6141 :         addrman->Add({addr}, ResolveIP(strAddr));
          +  -  +  +  -  
                      - ]
     550         [ +  + ]:        2047 :         if (i % 8 == 0)
     551         [ +  - ]:         255 :             addrman->Good(addr);
     552                 :        2047 :     }
     553         [ +  - ]:           1 :     std::vector<CAddress> vAddr = addrman->GetAddr(/*max_addresses=*/2500, /*max_pct=*/23, /*network=*/std::nullopt);
     554                 :             : 
     555         [ +  - ]:           1 :     size_t percent23 = (addrman->Size() * 23) / 100;
     556   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(vAddr.size(), percent23);
                   +  - ]
     557   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(vAddr.size(), 461U);
                   +  - ]
     558                 :             :     // (addrman.Size() < number of addresses added) due to address collisions.
     559   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 2006U);
                   +  - ]
     560                 :        2050 : }
     561                 :             : 
     562   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(getaddr_unfiltered)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     563                 :             : {
     564                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     565                 :             : 
     566                 :             :     // Set time on this addr so isTerrible = false
     567   [ +  -  +  - ]:           2 :     CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
     568                 :           1 :     addr1.nTime = Now<NodeSeconds>();
     569                 :             :     // Not setting time so this addr should be isTerrible = true
     570   [ +  -  +  - ]:           2 :     CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
     571                 :             : 
     572   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("250.1.2.1");
     573   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({addr1, addr2}, source));
          +  -  +  -  +  
                +  -  - ]
     574                 :             : 
     575                 :             :     // Set time on this addr so isTerrible = false
     576   [ +  -  +  - ]:           2 :     CAddress addr3 = CAddress(ResolveService("250.251.2.3", 9998), NODE_NONE);
     577                 :           1 :     addr3.nTime = Now<NodeSeconds>();
     578         [ +  - ]:           1 :     addrman->Good(addr3, /*time=*/Now<NodeSeconds>());
     579   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({addr3}, source));
          +  -  +  -  +  
                +  -  - ]
     580                 :             :     // The time is set, but after ADDRMAN_RETRIES unsuccessful attempts not
     581                 :             :     // retried in the last minute, this addr should be isTerrible = true
     582         [ +  + ]:           4 :     for (size_t i = 0; i < 3; ++i) {
     583         [ +  - ]:           3 :         addrman->Attempt(addr3, /*fCountFailure=*/true, /*time=*/Now<NodeSeconds>() - 61s);
     584                 :             :     }
     585                 :             : 
     586                 :             :     // Set time more than 10 minutes in the future (flying DeLorean), so this
     587                 :             :     // addr should be isTerrible = true
     588   [ +  -  +  - ]:           2 :     CAddress addr4 = CAddress(ResolveService("250.252.2.4", 9997), NODE_NONE);
     589                 :           1 :     addr4.nTime = Now<NodeSeconds>() + 11min;
     590   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({addr4}, source));
          +  -  +  -  +  
                +  -  - ]
     591                 :             : 
     592                 :             :     // GetAddr filtered by quality (i.e. not IsTerrible) should only return addr1
     593   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt).size(), 1U);
                   +  - ]
     594                 :             :     // Unfiltered GetAddr should return all addrs
     595   [ +  -  +  -  :           2 :     BOOST_CHECK_EQUAL(addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt, /*filtered=*/false).size(), 4U);
                   +  - ]
     596                 :           4 : }
     597                 :             : 
     598   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     599                 :             : {
     600         [ +  - ]:           2 :     CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
     601   [ +  -  +  - ]:           2 :     CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
     602                 :             : 
     603   [ +  -  +  - ]:           1 :     CNetAddr source1 = ResolveIP("250.1.1.1");
     604                 :             : 
     605                 :             : 
     606                 :           1 :     AddrInfo info1 = AddrInfo(addr1, source1);
     607                 :             : 
     608   [ +  -  +  -  :           1 :     uint256 nKey1 = (HashWriter{} << 1).GetHash();
                   +  - ]
     609   [ +  -  +  -  :           1 :     uint256 nKey2 = (HashWriter{} << 2).GetHash();
                   +  - ]
     610                 :             : 
     611   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN), 40);
                   +  - ]
     612                 :             : 
     613                 :             :     // Test: Make sure key actually randomizes bucket placement. A fail on
     614                 :             :     //  this test could be a security issue.
     615   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN) != info1.GetTriedBucket(nKey2, EMPTY_NETGROUPMAN));
             +  -  +  - ]
     616                 :             : 
     617                 :             :     // Test: Two addresses with same IP but different ports can map to
     618                 :             :     //  different buckets because they have different keys.
     619                 :           1 :     AddrInfo info2 = AddrInfo(addr2, source1);
     620                 :             : 
     621   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
          +  -  +  -  +  
                      - ]
     622   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN) != info2.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN));
             +  -  +  - ]
     623                 :             : 
     624                 :           1 :     std::set<int> buckets;
     625         [ +  + ]:         256 :     for (int i = 0; i < 255; i++) {
     626                 :         255 :         AddrInfo infoi = AddrInfo(
     627   [ +  -  +  -  :         510 :             CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
                   +  - ]
     628   [ +  -  +  -  :         765 :             ResolveIP("250.1.1." + ToString(i)));
                   +  - ]
     629         [ +  - ]:         255 :         int bucket = infoi.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN);
     630         [ +  - ]:         255 :         buckets.insert(bucket);
     631                 :         255 :     }
     632                 :             :     // Test: IP addresses in the same /16 prefix should
     633                 :             :     // never get more than 8 buckets with legacy grouping
     634   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(buckets.size(), 8U);
     635                 :             : 
     636                 :           1 :     buckets.clear();
     637         [ +  + ]:         256 :     for (int j = 0; j < 255; j++) {
     638                 :         255 :         AddrInfo infoj = AddrInfo(
     639   [ +  -  +  -  :         765 :             CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
                   +  - ]
     640   [ +  -  +  -  :        1020 :             ResolveIP("250." + ToString(j) + ".1.1"));
                   +  - ]
     641         [ +  - ]:         255 :         int bucket = infoj.GetTriedBucket(nKey1, EMPTY_NETGROUPMAN);
     642         [ +  - ]:         255 :         buckets.insert(bucket);
     643                 :         255 :     }
     644                 :             :     // Test: IP addresses in the different /16 prefix should map to more than
     645                 :             :     // 8 buckets with legacy grouping
     646   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(buckets.size(), 160U);
     647                 :           3 : }
     648                 :             : 
     649   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket_legacy)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     650                 :             : {
     651         [ +  - ]:           2 :     CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
     652   [ +  -  +  - ]:           2 :     CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
     653                 :             : 
     654   [ +  -  +  - ]:           1 :     CNetAddr source1 = ResolveIP("250.1.2.1");
     655                 :             : 
     656                 :           1 :     AddrInfo info1 = AddrInfo(addr1, source1);
     657                 :             : 
     658   [ +  -  +  -  :           1 :     uint256 nKey1 = (HashWriter{} << 1).GetHash();
                   +  - ]
     659   [ +  -  +  -  :           1 :     uint256 nKey2 = (HashWriter{} << 2).GetHash();
                   +  - ]
     660                 :             : 
     661                 :             :     // Test: Make sure the buckets are what we expect
     662   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, EMPTY_NETGROUPMAN), 786);
                   +  - ]
     663   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, EMPTY_NETGROUPMAN), 786);
                   +  - ]
     664                 :             : 
     665                 :             :     // Test: Make sure key actually randomizes bucket placement. A fail on
     666                 :             :     //  this test could be a security issue.
     667   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetNewBucket(nKey1, EMPTY_NETGROUPMAN) != info1.GetNewBucket(nKey2, EMPTY_NETGROUPMAN));
             +  -  +  - ]
     668                 :             : 
     669                 :             :     // Test: Ports should not affect bucket placement in the addr
     670                 :           1 :     AddrInfo info2 = AddrInfo(addr2, source1);
     671   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
          +  -  +  -  +  
                      - ]
     672   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, EMPTY_NETGROUPMAN), info2.GetNewBucket(nKey1, EMPTY_NETGROUPMAN));
             +  -  +  - ]
     673                 :             : 
     674                 :           1 :     std::set<int> buckets;
     675         [ +  + ]:         256 :     for (int i = 0; i < 255; i++) {
     676                 :         255 :         AddrInfo infoi = AddrInfo(
     677   [ +  -  +  -  :         510 :             CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
                   +  - ]
     678   [ +  -  +  -  :         765 :             ResolveIP("250.1.1." + ToString(i)));
                   +  - ]
     679         [ +  - ]:         255 :         int bucket = infoi.GetNewBucket(nKey1, EMPTY_NETGROUPMAN);
     680         [ +  - ]:         255 :         buckets.insert(bucket);
     681                 :         255 :     }
     682                 :             :     // Test: IP addresses in the same group (\16 prefix for IPv4) should
     683                 :             :     //  always map to the same bucket.
     684   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(buckets.size(), 1U);
     685                 :             : 
     686                 :           1 :     buckets.clear();
     687         [ +  + ]:        1021 :     for (int j = 0; j < 4 * 255; j++) {
     688                 :        1020 :         AddrInfo infoj = AddrInfo(CAddress(
     689                 :        1020 :                                         ResolveService(
     690   [ +  -  +  -  :        4080 :                                             ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
             +  -  +  - ]
     691   [ +  -  +  - ]:        3060 :             ResolveIP("251.4.1.1"));
     692         [ +  - ]:        1020 :         int bucket = infoj.GetNewBucket(nKey1, EMPTY_NETGROUPMAN);
     693         [ +  - ]:        1020 :         buckets.insert(bucket);
     694                 :        1020 :     }
     695                 :             :     // Test: IP addresses in the same source groups should map to NO MORE
     696                 :             :     //  than 64 buckets.
     697   [ +  -  +  - ]:           2 :     BOOST_CHECK(buckets.size() <= 64);
     698                 :             : 
     699                 :           1 :     buckets.clear();
     700         [ +  + ]:         256 :     for (int p = 0; p < 255; p++) {
     701                 :         255 :         AddrInfo infoj = AddrInfo(
     702   [ +  -  +  - ]:         510 :             CAddress(ResolveService("250.1.1.1"), NODE_NONE),
     703   [ +  -  +  -  :        1020 :             ResolveIP("250." + ToString(p) + ".1.1"));
                   +  - ]
     704         [ +  - ]:         255 :         int bucket = infoj.GetNewBucket(nKey1, EMPTY_NETGROUPMAN);
     705         [ +  - ]:         255 :         buckets.insert(bucket);
     706                 :         255 :     }
     707                 :             :     // Test: IP addresses in the different source groups should map to MORE
     708                 :             :     //  than 64 buckets.
     709   [ +  -  +  - ]:           2 :     BOOST_CHECK(buckets.size() > 64);
     710                 :           3 : }
     711                 :             : 
     712                 :             : // The following three test cases use asmap.raw
     713                 :             : // We use an artificial minimal mock mapping
     714                 :             : // 250.0.0.0/8 AS1000
     715                 :             : // 101.1.0.0/16 AS1
     716                 :             : // 101.2.0.0/16 AS2
     717                 :             : // 101.3.0.0/16 AS3
     718                 :             : // 101.4.0.0/16 AS4
     719                 :             : // 101.5.0.0/16 AS5
     720                 :             : // 101.6.0.0/16 AS6
     721                 :             : // 101.7.0.0/16 AS7
     722                 :             : // 101.8.0.0/16 AS8
     723   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     724                 :             : {
     725                 :           1 :     auto ngm_asmap{NetGroupManager::WithEmbeddedAsmap(test::data::asmap)};
     726                 :             : 
     727   [ +  -  +  - ]:           2 :     CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
     728   [ +  -  +  - ]:           2 :     CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
     729                 :             : 
     730   [ +  -  +  - ]:           1 :     CNetAddr source1 = ResolveIP("250.1.1.1");
     731                 :             : 
     732                 :             : 
     733                 :           1 :     AddrInfo info1 = AddrInfo(addr1, source1);
     734                 :             : 
     735   [ +  -  +  -  :           1 :     uint256 nKey1 = (HashWriter{} << 1).GetHash();
                   +  - ]
     736   [ +  -  +  -  :           1 :     uint256 nKey2 = (HashWriter{} << 2).GetHash();
                   +  - ]
     737                 :             : 
     738   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, ngm_asmap), 236);
                   +  - ]
     739                 :             : 
     740                 :             :     // Test: Make sure key actually randomizes bucket placement. A fail on
     741                 :             :     //  this test could be a security issue.
     742   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, ngm_asmap) != info1.GetTriedBucket(nKey2, ngm_asmap));
             +  -  +  - ]
     743                 :             : 
     744                 :             :     // Test: Two addresses with same IP but different ports can map to
     745                 :             :     //  different buckets because they have different keys.
     746                 :           1 :     AddrInfo info2 = AddrInfo(addr2, source1);
     747                 :             : 
     748   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
          +  -  +  -  +  
                      - ]
     749   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetTriedBucket(nKey1, ngm_asmap) != info2.GetTriedBucket(nKey1, ngm_asmap));
             +  -  +  - ]
     750                 :             : 
     751                 :           1 :     std::set<int> buckets;
     752         [ +  + ]:         256 :     for (int j = 0; j < 255; j++) {
     753                 :         255 :         AddrInfo infoj = AddrInfo(
     754   [ +  -  +  -  :         765 :             CAddress(ResolveService("101." + ToString(j) + ".1.1"), NODE_NONE),
                   +  - ]
     755   [ +  -  +  -  :        1020 :             ResolveIP("101." + ToString(j) + ".1.1"));
                   +  - ]
     756         [ +  - ]:         255 :         int bucket = infoj.GetTriedBucket(nKey1, ngm_asmap);
     757         [ +  - ]:         255 :         buckets.insert(bucket);
     758                 :         255 :     }
     759                 :             :     // Test: IP addresses in the different /16 prefix MAY map to more than
     760                 :             :     // 8 buckets.
     761   [ +  -  +  - ]:           2 :     BOOST_CHECK(buckets.size() > 8);
     762                 :             : 
     763                 :           1 :     buckets.clear();
     764         [ +  + ]:         256 :     for (int j = 0; j < 255; j++) {
     765                 :         255 :         AddrInfo infoj = AddrInfo(
     766   [ +  -  +  -  :         765 :             CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
                   +  - ]
     767   [ +  -  +  -  :        1020 :             ResolveIP("250." + ToString(j) + ".1.1"));
                   +  - ]
     768         [ +  - ]:         255 :         int bucket = infoj.GetTriedBucket(nKey1, ngm_asmap);
     769         [ +  - ]:         255 :         buckets.insert(bucket);
     770                 :         255 :     }
     771                 :             :     // Test: IP addresses in the different /16 prefix MAY NOT map to more than
     772                 :             :     // 8 buckets.
     773   [ +  -  +  - ]:           2 :     BOOST_CHECK(buckets.size() == 8);
     774                 :           3 : }
     775                 :             : 
     776   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     777                 :             : {
     778                 :           1 :     auto ngm_asmap{NetGroupManager::WithEmbeddedAsmap(test::data::asmap)};
     779                 :             : 
     780   [ +  -  +  - ]:           2 :     CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
     781   [ +  -  +  - ]:           2 :     CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
     782                 :             : 
     783   [ +  -  +  - ]:           1 :     CNetAddr source1 = ResolveIP("250.1.2.1");
     784                 :             : 
     785                 :           1 :     AddrInfo info1 = AddrInfo(addr1, source1);
     786                 :             : 
     787   [ +  -  +  -  :           1 :     uint256 nKey1 = (HashWriter{} << 1).GetHash();
                   +  - ]
     788   [ +  -  +  -  :           1 :     uint256 nKey2 = (HashWriter{} << 2).GetHash();
                   +  - ]
     789                 :             : 
     790                 :             :     // Test: Make sure the buckets are what we expect
     791   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, ngm_asmap), 795);
                   +  - ]
     792   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, ngm_asmap), 795);
                   +  - ]
     793                 :             : 
     794                 :             :     // Test: Make sure key actually randomizes bucket placement. A fail on
     795                 :             :     //  this test could be a security issue.
     796   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetNewBucket(nKey1, ngm_asmap) != info1.GetNewBucket(nKey2, ngm_asmap));
             +  -  +  - ]
     797                 :             : 
     798                 :             :     // Test: Ports should not affect bucket placement in the addr
     799                 :           1 :     AddrInfo info2 = AddrInfo(addr2, source1);
     800   [ +  -  +  -  :           2 :     BOOST_CHECK(info1.GetKey() != info2.GetKey());
          +  -  +  -  +  
                      - ]
     801   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, ngm_asmap), info2.GetNewBucket(nKey1, ngm_asmap));
             +  -  +  - ]
     802                 :             : 
     803                 :           1 :     std::set<int> buckets;
     804         [ +  + ]:         256 :     for (int i = 0; i < 255; i++) {
     805                 :         255 :         AddrInfo infoi = AddrInfo(
     806   [ +  -  +  -  :         510 :             CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
                   +  - ]
     807   [ +  -  +  -  :         765 :             ResolveIP("250.1.1." + ToString(i)));
                   +  - ]
     808         [ +  - ]:         255 :         int bucket = infoi.GetNewBucket(nKey1, ngm_asmap);
     809         [ +  - ]:         255 :         buckets.insert(bucket);
     810                 :         255 :     }
     811                 :             :     // Test: IP addresses in the same /16 prefix
     812                 :             :     // usually map to the same bucket.
     813   [ +  -  +  - ]:           1 :     BOOST_CHECK_EQUAL(buckets.size(), 1U);
     814                 :             : 
     815                 :           1 :     buckets.clear();
     816         [ +  + ]:        1021 :     for (int j = 0; j < 4 * 255; j++) {
     817                 :        1020 :         AddrInfo infoj = AddrInfo(CAddress(
     818                 :        1020 :                                         ResolveService(
     819   [ +  -  +  -  :        4080 :                                             ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
             +  -  +  - ]
     820   [ +  -  +  - ]:        3060 :             ResolveIP("251.4.1.1"));
     821         [ +  - ]:        1020 :         int bucket = infoj.GetNewBucket(nKey1, ngm_asmap);
     822         [ +  - ]:        1020 :         buckets.insert(bucket);
     823                 :        1020 :     }
     824                 :             :     // Test: IP addresses in the same source /16 prefix should not map to more
     825                 :             :     // than 64 buckets.
     826   [ +  -  +  - ]:           2 :     BOOST_CHECK(buckets.size() <= 64);
     827                 :             : 
     828                 :           1 :     buckets.clear();
     829         [ +  + ]:         256 :     for (int p = 0; p < 255; p++) {
     830                 :         255 :         AddrInfo infoj = AddrInfo(
     831   [ +  -  +  - ]:         510 :             CAddress(ResolveService("250.1.1.1"), NODE_NONE),
     832   [ +  -  +  -  :        1020 :             ResolveIP("101." + ToString(p) + ".1.1"));
                   +  - ]
     833         [ +  - ]:         255 :         int bucket = infoj.GetNewBucket(nKey1, ngm_asmap);
     834         [ +  - ]:         255 :         buckets.insert(bucket);
     835                 :         255 :     }
     836                 :             :     // Test: IP addresses in the different source /16 prefixes usually map to MORE
     837                 :             :     // than 1 bucket.
     838   [ +  -  +  - ]:           2 :     BOOST_CHECK(buckets.size() > 1);
     839                 :             : 
     840                 :           1 :     buckets.clear();
     841         [ +  + ]:         256 :     for (int p = 0; p < 255; p++) {
     842                 :         255 :         AddrInfo infoj = AddrInfo(
     843   [ +  -  +  - ]:         510 :             CAddress(ResolveService("250.1.1.1"), NODE_NONE),
     844   [ +  -  +  -  :        1020 :             ResolveIP("250." + ToString(p) + ".1.1"));
                   +  - ]
     845         [ +  - ]:         255 :         int bucket = infoj.GetNewBucket(nKey1, ngm_asmap);
     846         [ +  - ]:         255 :         buckets.insert(bucket);
     847                 :         255 :     }
     848                 :             :     // Test: IP addresses in the different source /16 prefixes sometimes map to NO MORE
     849                 :             :     // than 1 bucket.
     850   [ +  -  +  - ]:           2 :     BOOST_CHECK(buckets.size() == 1);
     851                 :           3 : }
     852                 :             : 
     853   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_serialization)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     854                 :             : {
     855                 :           1 :     auto netgroupman{NetGroupManager::WithEmbeddedAsmap(test::data::asmap)};
     856                 :             : 
     857         [ +  - ]:           1 :     const auto ratio = GetCheckRatio(m_node);
     858         [ +  - ]:           1 :     auto addrman_asmap1 = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);
     859         [ +  - ]:           1 :     auto addrman_asmap1_dup = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);
     860         [ +  - ]:           1 :     auto addrman_noasmap = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, ratio);
     861                 :             : 
     862                 :           1 :     DataStream stream{};
     863                 :             : 
     864   [ +  -  +  - ]:           2 :     CAddress addr = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
     865         [ +  - ]:           1 :     CNetAddr default_source;
     866                 :             : 
     867   [ +  -  +  -  :           2 :     addrman_asmap1->Add({addr}, default_source);
             +  +  -  - ]
     868                 :             : 
     869         [ +  - ]:           1 :     stream << *addrman_asmap1;
     870                 :             :     // serizalizing/deserializing addrman with the same asmap
     871         [ +  - ]:           1 :     stream >> *addrman_asmap1_dup;
     872                 :             : 
     873         [ +  - ]:           1 :     AddressPosition addr_pos1 = addrman_asmap1->FindAddressEntry(addr).value();
     874         [ +  - ]:           1 :     AddressPosition addr_pos2 = addrman_asmap1_dup->FindAddressEntry(addr).value();
     875   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos1.multiplicity != 0);
                   +  - ]
     876   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos2.multiplicity != 0);
                   +  - ]
     877                 :             : 
     878   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos1 == addr_pos2);
                   +  - ]
     879                 :             : 
     880                 :             :     // deserializing asmaped peers.dat to non-asmaped addrman
     881         [ +  - ]:           1 :     stream << *addrman_asmap1;
     882         [ +  - ]:           1 :     stream >> *addrman_noasmap;
     883         [ +  - ]:           1 :     AddressPosition addr_pos3 = addrman_noasmap->FindAddressEntry(addr).value();
     884   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos3.multiplicity != 0);
                   +  - ]
     885   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos1.bucket != addr_pos3.bucket);
                   +  - ]
     886   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos1.position != addr_pos3.position);
                   +  - ]
     887                 :             : 
     888                 :             :     // deserializing non-asmaped peers.dat to asmaped addrman
     889         [ +  - ]:           2 :     addrman_asmap1 = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);
     890         [ +  - ]:           2 :     addrman_noasmap = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, ratio);
     891   [ +  -  +  -  :           2 :     addrman_noasmap->Add({addr}, default_source);
             +  +  -  - ]
     892         [ +  - ]:           1 :     stream << *addrman_noasmap;
     893         [ +  - ]:           1 :     stream >> *addrman_asmap1;
     894                 :             : 
     895         [ +  - ]:           1 :     AddressPosition addr_pos4 = addrman_asmap1->FindAddressEntry(addr).value();
     896   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos4.multiplicity != 0);
                   +  - ]
     897   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos4.bucket != addr_pos3.bucket);
                   +  - ]
     898   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos4 == addr_pos2);
                   +  - ]
     899                 :             : 
     900                 :             :     // used to map to different buckets, now maps to the same bucket.
     901         [ +  - ]:           2 :     addrman_asmap1 = std::make_unique<AddrMan>(netgroupman, DETERMINISTIC, ratio);
     902         [ +  - ]:           2 :     addrman_noasmap = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, ratio);
     903   [ +  -  +  - ]:           2 :     CAddress addr1 = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
     904   [ +  -  +  - ]:           2 :     CAddress addr2 = CAddress(ResolveService("250.2.1.1"), NODE_NONE);
     905   [ +  -  +  -  :           4 :     addrman_noasmap->Add({addr, addr2}, default_source);
             +  +  -  - ]
     906         [ +  - ]:           1 :     AddressPosition addr_pos5 = addrman_noasmap->FindAddressEntry(addr1).value();
     907         [ +  - ]:           1 :     AddressPosition addr_pos6 = addrman_noasmap->FindAddressEntry(addr2).value();
     908   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos5.bucket != addr_pos6.bucket);
                   +  - ]
     909         [ +  - ]:           1 :     stream << *addrman_noasmap;
     910         [ +  - ]:           1 :     stream >> *addrman_asmap1;
     911         [ +  - ]:           1 :     AddressPosition addr_pos7 = addrman_asmap1->FindAddressEntry(addr1).value();
     912         [ +  - ]:           1 :     AddressPosition addr_pos8 = addrman_asmap1->FindAddressEntry(addr2).value();
     913   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos7.bucket == addr_pos8.bucket);
                   +  - ]
     914   [ +  -  +  - ]:           2 :     BOOST_CHECK(addr_pos7.position != addr_pos8.position);
     915                 :           4 : }
     916                 :             : 
     917   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(remove_invalid)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     918                 :             : {
     919                 :             :     // Confirm that invalid addresses are ignored in unserialization.
     920                 :             : 
     921                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     922                 :           1 :     DataStream stream{};
     923                 :             : 
     924   [ +  -  +  - ]:           2 :     const CAddress new1{ResolveService("5.5.5.5"), NODE_NONE};
     925   [ +  -  +  - ]:           2 :     const CAddress new2{ResolveService("6.6.6.6"), NODE_NONE};
     926   [ +  -  +  - ]:           2 :     const CAddress tried1{ResolveService("7.7.7.7"), NODE_NONE};
     927   [ +  -  +  - ]:           2 :     const CAddress tried2{ResolveService("8.8.8.8"), NODE_NONE};
     928                 :             : 
     929   [ +  -  +  -  :           6 :     addrman->Add({new1, tried1, new2, tried2}, CNetAddr{});
          +  -  +  +  -  
                      - ]
     930         [ +  - ]:           1 :     addrman->Good(tried1);
     931         [ +  - ]:           1 :     addrman->Good(tried2);
     932   [ +  -  +  -  :           1 :     BOOST_REQUIRE_EQUAL(addrman->Size(), 4);
                   +  - ]
     933                 :             : 
     934         [ +  - ]:           1 :     stream << *addrman;
     935                 :             : 
     936         [ +  - ]:           1 :     const std::string str{stream.str()};
     937                 :           1 :     size_t pos;
     938                 :             : 
     939                 :           1 :     const char new2_raw[]{6, 6, 6, 6};
     940                 :           1 :     const uint8_t new2_raw_replacement[]{0, 0, 0, 0}; // 0.0.0.0 is !IsValid()
     941                 :           1 :     pos = str.find(new2_raw, 0, sizeof(new2_raw));
     942   [ +  -  +  -  :           2 :     BOOST_REQUIRE(pos != std::string::npos);
                   +  - ]
     943   [ +  -  -  +  :           2 :     BOOST_REQUIRE(pos + sizeof(new2_raw_replacement) <= stream.size());
                   +  - ]
     944                 :           1 :     memcpy(stream.data() + pos, new2_raw_replacement, sizeof(new2_raw_replacement));
     945                 :             : 
     946                 :           1 :     const char tried2_raw[]{8, 8, 8, 8};
     947                 :           1 :     const uint8_t tried2_raw_replacement[]{255, 255, 255, 255}; // 255.255.255.255 is !IsValid()
     948                 :           1 :     pos = str.find(tried2_raw, 0, sizeof(tried2_raw));
     949   [ +  -  +  -  :           2 :     BOOST_REQUIRE(pos != std::string::npos);
                   +  - ]
     950   [ +  -  -  +  :           2 :     BOOST_REQUIRE(pos + sizeof(tried2_raw_replacement) <= stream.size());
             +  -  +  - ]
     951         [ +  - ]:           1 :     memcpy(stream.data() + pos, tried2_raw_replacement, sizeof(tried2_raw_replacement));
     952                 :             : 
     953   [ +  -  +  - ]:           2 :     addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     954         [ +  - ]:           1 :     stream >> *addrman;
     955   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 2);
                   +  - ]
     956                 :           2 : }
     957                 :             : 
     958   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     959                 :             : {
     960                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     961                 :             : 
     962   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Size() == 0);
             +  -  +  - ]
     963                 :             : 
     964                 :             :     // Empty addrman should return blank addrman info.
     965   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
          +  -  +  -  +  
                      - ]
     966                 :             : 
     967                 :             :     // Add twenty two addresses.
     968   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
     969         [ +  + ]:          23 :     for (unsigned int i = 1; i < 23; i++) {
     970   [ +  -  +  -  :          44 :         CService addr = ResolveService("250.1.1." + ToString(i));
                   +  - ]
     971   [ +  -  +  -  :         110 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
     972                 :             : 
     973                 :             :         // No collisions in tried.
     974   [ +  -  +  -  :          44 :         BOOST_CHECK(addrman->Good(addr));
             +  -  +  - ]
     975   [ +  -  +  -  :          44 :         BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
             +  -  +  - ]
     976                 :          22 :     }
     977                 :             : 
     978                 :             :     // Ensure Good handles duplicates well.
     979                 :             :     // If an address is a duplicate, Good will return false but will not count it as a collision.
     980         [ +  + ]:          23 :     for (unsigned int i = 1; i < 23; i++) {
     981   [ +  -  +  -  :          44 :         CService addr = ResolveService("250.1.1." + ToString(i));
                   +  - ]
     982                 :             : 
     983                 :             :         // Unable to add duplicate address to tried table.
     984   [ +  -  +  -  :          44 :         BOOST_CHECK(!addrman->Good(addr));
             +  -  +  - ]
     985                 :             : 
     986                 :             :         // Verify duplicate address not marked as a collision.
     987   [ +  -  +  -  :          44 :         BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
             +  -  +  - ]
     988                 :          22 :     }
     989         [ +  - ]:          45 : }
     990                 :             : 
     991   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_noevict)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
     992                 :             : {
     993                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
     994                 :             : 
     995                 :             :     // Add 35 addresses.
     996   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
     997         [ +  + ]:          36 :     for (unsigned int i = 1; i < 36; i++) {
     998   [ +  -  +  -  :          70 :         CService addr = ResolveService("250.1.1." + ToString(i));
                   +  - ]
     999   [ +  -  +  -  :         175 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
    1000                 :             : 
    1001                 :             :         // No collision yet.
    1002   [ +  -  +  -  :          70 :         BOOST_CHECK(addrman->Good(addr));
                   +  - ]
    1003                 :          35 :     }
    1004                 :             : 
    1005                 :             :     // Collision in tried table between 36 and 19.
    1006   [ +  -  +  - ]:           1 :     CService addr36 = ResolveService("250.1.1.36");
    1007   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr36, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
    1008   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Good(addr36));
             +  -  +  - ]
    1009   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.19:0");
             +  -  +  - ]
    1010                 :             : 
    1011                 :             :     // 36 should be discarded and 19 not evicted.
    1012                 :             :     // This means we keep 19 in the tried table and
    1013                 :             :     // 36 stays in the new table.
    1014         [ +  - ]:           1 :     addrman->ResolveCollisions();
    1015   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
             +  -  +  - ]
    1016                 :             : 
    1017                 :             :     // Lets create two collisions.
    1018         [ +  + ]:          23 :     for (unsigned int i = 37; i < 59; i++) {
    1019   [ +  -  +  -  :          44 :         CService addr = ResolveService("250.1.1." + ToString(i));
                   +  - ]
    1020   [ +  -  +  -  :         110 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
    1021   [ +  -  +  -  :          44 :         BOOST_CHECK(addrman->Good(addr));
                   +  - ]
    1022                 :          22 :     }
    1023                 :             : 
    1024                 :             :     // Cause a collision in the tried table.
    1025   [ +  -  +  - ]:           1 :     CService addr59 = ResolveService("250.1.1.59");
    1026   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr59, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
    1027   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Good(addr59));
             +  -  +  - ]
    1028                 :             : 
    1029   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.10:0");
             +  -  +  - ]
    1030                 :             : 
    1031                 :             :     // Cause a second collision in the new table.
    1032   [ +  -  +  -  :           5 :     BOOST_CHECK(!addrman->Add({CAddress(addr36, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
    1033                 :             : 
    1034                 :             :     // 36 still cannot be moved from new to tried due to colliding with 19
    1035   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Good(addr36));
             +  -  +  - ]
    1036   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() != "[::]:0");
          +  -  +  -  +  
                      - ]
    1037                 :             : 
    1038                 :             :     // Resolve all collisions.
    1039         [ +  - ]:           1 :     addrman->ResolveCollisions();
    1040   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
             +  -  +  - ]
    1041   [ +  -  +  -  :         121 : }
          +  -  +  -  +  
                      - ]
    1042                 :             : 
    1043   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_evictionworks)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
    1044                 :             : {
    1045                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
    1046                 :             : 
    1047   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Size() == 0);
             +  -  +  - ]
    1048                 :             : 
    1049                 :             :     // Empty addrman should return blank addrman info.
    1050   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
          +  -  +  -  +  
                      - ]
    1051                 :             : 
    1052                 :             :     // Add 35 addresses
    1053   [ +  -  +  - ]:           1 :     CNetAddr source = ResolveIP("252.2.2.2");
    1054         [ +  + ]:          36 :     for (unsigned int i = 1; i < 36; i++) {
    1055   [ +  -  +  -  :          70 :         CService addr = ResolveService("250.1.1." + ToString(i));
                   +  - ]
    1056   [ +  -  +  -  :         175 :         BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
    1057                 :             : 
    1058                 :             :         // No collision yet.
    1059   [ +  -  +  -  :          70 :         BOOST_CHECK(addrman->Good(addr));
                   +  - ]
    1060                 :          35 :     }
    1061                 :             : 
    1062                 :             :     // Collision between 36 and 19.
    1063   [ +  -  +  - ]:           1 :     CService addr = ResolveService("250.1.1.36");
    1064   [ +  -  +  -  :           5 :     BOOST_CHECK(addrman->Add({CAddress(addr, NODE_NONE)}, source));
          +  -  +  +  +  
                -  -  - ]
    1065   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Good(addr));
             +  -  +  - ]
    1066                 :             : 
    1067         [ +  - ]:           1 :     auto info = addrman->SelectTriedCollision().first;
    1068   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(info.ToStringAddrPort(), "250.1.1.19:0");
                   +  - ]
    1069                 :             : 
    1070                 :             :     // Ensure test of address fails, so that it is evicted.
    1071                 :             :     // Update entry in tried by setting last good connection in the deep past.
    1072   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Good(info, NodeSeconds{1s}));
                   +  - ]
    1073         [ +  - ]:           1 :     addrman->Attempt(info, /*fCountFailure=*/false, Now<NodeSeconds>() - 61s);
    1074                 :             : 
    1075                 :             :     // Should swap 36 for 19.
    1076         [ +  - ]:           1 :     addrman->ResolveCollisions();
    1077   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
             +  -  +  - ]
    1078         [ +  - ]:           2 :     AddressPosition addr_pos{addrman->FindAddressEntry(CAddress(addr, NODE_NONE)).value()};
    1079   [ +  -  +  -  :           2 :     BOOST_CHECK(addr_pos.tried);
                   +  - ]
    1080                 :             : 
    1081                 :             :     // If 36 was swapped for 19, then adding 36 to tried should fail because we
    1082                 :             :     // are attempting to add a duplicate.
    1083                 :             :     // We check this by verifying Good() returns false and also verifying that
    1084                 :             :     // we have no collisions.
    1085   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Good(addr));
             +  -  +  - ]
    1086   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
          +  -  +  -  +  
                      - ]
    1087                 :             : 
    1088                 :             :     // 19 should fail as a collision (not a duplicate) if we now attempt to move
    1089                 :             :     // it to the tried table.
    1090   [ +  -  +  - ]:           1 :     CService addr19 = ResolveService("250.1.1.19");
    1091   [ +  -  +  -  :           2 :     BOOST_CHECK(!addrman->Good(addr19));
             +  -  +  - ]
    1092   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->SelectTriedCollision().first.ToStringAddrPort(), "250.1.1.36:0");
             +  -  +  - ]
    1093                 :             : 
    1094                 :             :     // Eviction is also successful if too much time has passed since last try
    1095         [ +  - ]:           1 :     FakeNodeClock clock{};
    1096         [ +  - ]:           1 :     clock += 4h;
    1097         [ +  - ]:           1 :     addrman->ResolveCollisions();
    1098   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->SelectTriedCollision().first.ToStringAddrPort() == "[::]:0");
             +  -  +  - ]
    1099                 :             :     //Now 19 is in tried again, and 36 back to new
    1100         [ +  - ]:           2 :     AddressPosition addr_pos19{addrman->FindAddressEntry(CAddress(addr19, NODE_NONE)).value()};
    1101   [ +  -  +  - ]:           2 :     BOOST_CHECK(addr_pos19.tried);
    1102         [ +  - ]:           2 :     AddressPosition addr_pos36{addrman->FindAddressEntry(CAddress(addr, NODE_NONE)).value()};
    1103   [ +  -  +  - ]:           2 :     BOOST_CHECK(!addr_pos36.tried);
    1104   [ +  -  +  - ]:          73 : }
    1105                 :             : 
    1106                 :           2 : static auto AddrmanToStream(const AddrMan& addrman)
    1107                 :             : {
    1108                 :           2 :     DataStream ssPeersIn{};
    1109   [ +  -  +  - ]:           2 :     ssPeersIn << Params().MessageStart();
    1110         [ +  - ]:           2 :     ssPeersIn << addrman;
    1111                 :           2 :     return ssPeersIn;
    1112                 :           0 : }
    1113                 :             : 
    1114   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(load_addrman)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
    1115                 :             : {
    1116                 :           1 :     AddrMan addrman{EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node)};
    1117                 :             : 
    1118                 :           1 :     std::optional<CService> addr1, addr2, addr3, addr4;
    1119   [ +  -  +  -  :           2 :     addr1 = Lookup("250.7.1.1", 8333, false);
                   +  - ]
    1120   [ +  -  +  -  :           2 :     BOOST_CHECK(addr1.has_value());
                   +  - ]
    1121   [ +  -  +  -  :           2 :     addr2 = Lookup("250.7.2.2", 9999, false);
                   +  - ]
    1122   [ +  -  +  -  :           2 :     BOOST_CHECK(addr2.has_value());
                   +  - ]
    1123   [ +  -  +  -  :           2 :     addr3 = Lookup("250.7.3.3", 9999, false);
                   +  - ]
    1124   [ +  -  +  -  :           2 :     BOOST_CHECK(addr3.has_value());
                   +  - ]
    1125   [ +  -  +  - ]:           3 :     addr3 = Lookup("250.7.3.3"s, 9999, false);
    1126   [ +  -  +  -  :           2 :     BOOST_CHECK(addr3.has_value());
                   +  - ]
    1127   [ +  -  +  - ]:           3 :     addr4 = Lookup("250.7.3.3\0example.com"s, 9999, false);
    1128   [ +  -  +  -  :           2 :     BOOST_CHECK(!addr4.has_value());
                   +  - ]
    1129                 :             : 
    1130                 :             :     // Add three addresses to new table.
    1131   [ +  -  +  -  :           2 :     const std::optional<CService> source{Lookup("252.5.1.1", 8333, false)};
                   +  - ]
    1132   [ +  -  +  -  :           2 :     BOOST_CHECK(source.has_value());
                   +  - ]
    1133   [ +  +  -  - ]:           8 :     std::vector<CAddress> addresses{CAddress(addr1.value(), NODE_NONE), CAddress(addr2.value(), NODE_NONE), CAddress(addr3.value(), NODE_NONE)};
    1134   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman.Add(addresses, source.value()));
          +  -  +  -  +  
                      - ]
    1135   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman.Size() == 3);
             +  -  +  - ]
    1136                 :             : 
    1137                 :             :     // Test that the de-serialization does not throw an exception.
    1138         [ +  - ]:           1 :     auto ssPeers1{AddrmanToStream(addrman)};
    1139   [ +  -  +  - ]:           1 :     AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
    1140                 :             : 
    1141   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman1.Size() == 0);
             +  -  +  - ]
    1142                 :           1 :     {
    1143                 :           1 :         unsigned char pchMsgTmp[4];
    1144   [ +  -  +  -  :           3 :         BOOST_CHECK_NO_THROW(ssPeers1 >> pchMsgTmp >> addrman1);
          +  -  +  -  -  
             -  -  -  -  
                      - ]
    1145                 :             :     }
    1146                 :             : 
    1147   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman1.Size() == 3);
             +  -  +  - ]
    1148                 :             : 
    1149                 :             :     // Test that ReadFromStream creates an addrman with the correct number of addrs.
    1150         [ +  - ]:           1 :     DataStream ssPeers2 = AddrmanToStream(addrman);
    1151                 :             : 
    1152   [ +  -  +  - ]:           1 :     AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
    1153   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman2.Size() == 0);
             +  -  +  - ]
    1154         [ +  - ]:           1 :     ReadFromStream(addrman2, ssPeers2);
    1155   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman2.Size() == 3);
                   +  - ]
    1156   [ +  -  +  -  :           5 : }
          +  -  -  +  -  
                      - ]
    1157                 :             : 
    1158                 :             : // Produce a corrupt peers.dat that claims 20 addrs when it only has one addr.
    1159                 :           2 : static auto MakeCorruptPeersDat()
    1160                 :             : {
    1161                 :           2 :     DataStream s{};
    1162   [ +  -  +  - ]:           2 :     s << ::Params().MessageStart();
    1163                 :             : 
    1164                 :           2 :     unsigned char nVersion = 1;
    1165         [ +  - ]:           2 :     s << nVersion;
    1166         [ +  - ]:           2 :     s << ((unsigned char)32);
    1167         [ +  - ]:           2 :     s << uint256::ONE;
    1168         [ +  - ]:           2 :     s << 10; // nNew
    1169         [ +  - ]:           2 :     s << 10; // nTried
    1170                 :             : 
    1171                 :           2 :     int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
    1172         [ +  - ]:           2 :     s << nUBuckets;
    1173                 :             : 
    1174   [ +  -  +  -  :           4 :     const std::optional<CService> serv{Lookup("252.1.1.1", 7777, false)};
                   +  - ]
    1175   [ +  -  +  -  :           4 :     BOOST_REQUIRE(serv.has_value());
                   +  - ]
    1176         [ +  - ]:           2 :     CAddress addr = CAddress(serv.value(), NODE_NONE);
    1177   [ +  -  +  -  :           4 :     std::optional<CNetAddr> resolved{LookupHost("252.2.2.2", false)};
                   +  - ]
    1178   [ +  -  +  -  :           4 :     BOOST_REQUIRE(resolved.has_value());
                   +  - ]
    1179         [ +  - ]:           2 :     AddrInfo info = AddrInfo(addr, resolved.value());
    1180         [ +  - ]:           2 :     s << CAddress::V1_DISK(info);
    1181                 :             : 
    1182                 :           2 :     return s;
    1183                 :           2 : }
    1184                 :             : 
    1185   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
    1186                 :             : {
    1187                 :             :     // Test that the de-serialization of corrupted peers.dat throws an exception.
    1188                 :           1 :     auto ssPeers1{MakeCorruptPeersDat()};
    1189   [ +  -  +  - ]:           1 :     AddrMan addrman1{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
    1190   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman1.Size() == 0);
             +  -  +  - ]
    1191   [ +  -  -  +  :           3 :     BOOST_CHECK_EXCEPTION([&]
          -  -  -  -  -  
          +  +  -  +  -  
                   +  - ]
    1192                 :             :     {
    1193                 :             :         unsigned char pchMsgTmp[4];
    1194                 :             :         ssPeers1 >> pchMsgTmp;
    1195                 :             :         ssPeers1 >> addrman1;
    1196                 :             :     }(), std::ios_base::failure, HasReason{"end of data"});
    1197                 :             : 
    1198                 :             :     // Test that ReadFromStream fails if peers.dat is corrupt
    1199         [ +  - ]:           1 :     auto ssPeers2{MakeCorruptPeersDat()};
    1200                 :             : 
    1201   [ +  -  +  - ]:           1 :     AddrMan addrman2{EMPTY_NETGROUPMAN, !DETERMINISTIC, GetCheckRatio(m_node)};
    1202   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman2.Size() == 0);
             +  -  +  - ]
    1203   [ +  -  -  +  :           2 :     BOOST_CHECK_THROW(ReadFromStream(addrman2, ssPeers2), std::ios_base::failure);
          -  -  -  -  -  
             +  +  -  +  
                      - ]
    1204                 :           1 : }
    1205                 :             : 
    1206   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_update_address)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
    1207                 :             : {
    1208                 :             :     // Tests updating nTime via Connected() and nServices via SetServices() and Add()
    1209                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
    1210   [ +  -  +  - ]:           1 :     CNetAddr source{ResolveIP("252.2.2.2")};
    1211   [ +  -  +  - ]:           2 :     CAddress addr{CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE)};
    1212                 :             : 
    1213                 :           1 :     const auto start_time{Now<NodeSeconds>() - 10000s};
    1214                 :           1 :     addr.nTime = start_time;
    1215   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({addr}, source));
          +  -  +  -  +  
                +  -  - ]
    1216   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(), 1U);
                   +  - ]
    1217                 :             : 
    1218                 :             :     // Updating an addrman entry with a different port doesn't change it
    1219   [ +  -  +  - ]:           2 :     CAddress addr_diff_port{CAddress(ResolveService("250.1.1.1", 8334), NODE_NONE)};
    1220                 :           1 :     addr_diff_port.nTime = start_time;
    1221         [ +  - ]:           1 :     addrman->Connected(addr_diff_port);
    1222         [ +  - ]:           1 :     addrman->SetServices(addr_diff_port, NODE_NETWORK_LIMITED);
    1223         [ +  - ]:           1 :     std::vector<CAddress> vAddr1{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
    1224   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(vAddr1.size(), 1U);
                   +  - ]
    1225   [ +  -  +  -  :           2 :     BOOST_CHECK(vAddr1.at(0).nTime == start_time);
             +  -  +  - ]
    1226   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(vAddr1.at(0).nServices, NODE_NONE);
                   +  - ]
    1227                 :             : 
    1228                 :             :     // Updating an addrman entry with the correct port is successful
    1229         [ +  - ]:           1 :     addrman->Connected(addr);
    1230         [ +  - ]:           1 :     addrman->SetServices(addr, NODE_NETWORK_LIMITED);
    1231         [ +  - ]:           1 :     std::vector<CAddress> vAddr2 = addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt);
    1232   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(vAddr2.size(), 1U);
                   +  - ]
    1233   [ +  -  +  -  :           2 :     BOOST_CHECK(vAddr2.at(0).nTime >= start_time + 10000s);
             +  -  +  - ]
    1234   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(vAddr2.at(0).nServices, NODE_NETWORK_LIMITED);
                   +  - ]
    1235                 :             : 
    1236                 :             :     // Updating an existing addr through Add() (used in gossip relay) can add additional services but can't remove existing ones.
    1237   [ +  -  +  - ]:           2 :     CAddress addr_v2{CAddress(ResolveService("250.1.1.1", 8333), NODE_P2P_V2)};
    1238                 :           1 :     addr_v2.nTime = start_time;
    1239   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Add({addr_v2}, source));
          +  -  +  -  +  
                +  -  - ]
    1240         [ +  - ]:           1 :     std::vector<CAddress> vAddr3{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
    1241   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(vAddr3.size(), 1U);
                   +  - ]
    1242   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(vAddr3.at(0).nServices, NODE_P2P_V2 | NODE_NETWORK_LIMITED);
                   +  - ]
    1243                 :             : 
    1244                 :             :     // SetServices() (used when we connected to them) overwrites existing service flags
    1245         [ +  - ]:           1 :     addrman->SetServices(addr, NODE_NETWORK);
    1246         [ +  - ]:           1 :     std::vector<CAddress> vAddr4{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
    1247   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(vAddr4.size(), 1U);
                   +  - ]
    1248   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(vAddr4.at(0).nServices, NODE_NETWORK);
                   +  - ]
    1249                 :             : 
    1250                 :             :     // Promoting to Tried does not affect the service flags
    1251   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(addr)); // addr has NODE_NONE
             +  -  +  - ]
    1252         [ +  - ]:           1 :     std::vector<CAddress> vAddr5{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
    1253   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(vAddr5.size(), 1U);
                   +  - ]
    1254   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(vAddr5.at(0).nServices, NODE_NETWORK);
                   +  - ]
    1255                 :             : 
    1256                 :             :     // Adding service flags even works when the addr is in Tried
    1257   [ +  -  +  -  :           3 :     BOOST_CHECK(!addrman->Add({addr_v2}, source));
          +  -  +  -  +  
                +  -  - ]
    1258         [ +  - ]:           1 :     std::vector<CAddress> vAddr6{addrman->GetAddr(/*max_addresses=*/0, /*max_pct=*/0, /*network=*/std::nullopt)};
    1259   [ +  -  -  +  :           1 :     BOOST_CHECK_EQUAL(vAddr6.size(), 1U);
                   +  - ]
    1260   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(vAddr6.at(0).nServices, NODE_NETWORK | NODE_P2P_V2);
                   +  - ]
    1261                 :           4 : }
    1262                 :             : 
    1263   [ +  -  +  -  :           7 : BOOST_AUTO_TEST_CASE(addrman_size)
          +  -  +  -  -  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
          -  +  -  +  -  
          +  -  +  -  +  
          -  +  -  -  +  
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  -  +  +  
                      - ]
    1264                 :             : {
    1265                 :           1 :     auto addrman = std::make_unique<AddrMan>(EMPTY_NETGROUPMAN, DETERMINISTIC, GetCheckRatio(m_node));
    1266   [ +  -  +  - ]:           1 :     const CNetAddr source = ResolveIP("252.2.2.2");
    1267                 :             : 
    1268                 :             :     // empty addrman
    1269   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 0U);
                   +  - ]
    1270   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 0U);
                   +  - ]
    1271   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 0U);
                   +  - ]
    1272   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 0U);
                   +  - ]
    1273                 :             : 
    1274                 :             :     // add two ipv4 addresses, one to tried and new
    1275   [ +  -  +  - ]:           2 :     const CAddress addr1{ResolveService("250.1.1.1", 8333), NODE_NONE};
    1276   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({addr1}, source));
          +  -  +  -  +  
                +  -  - ]
    1277   [ +  -  +  -  :           2 :     BOOST_CHECK(addrman->Good(addr1));
             +  -  +  - ]
    1278   [ +  -  +  - ]:           2 :     const CAddress addr2{ResolveService("250.1.1.2", 8333), NODE_NONE};
    1279   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({addr2}, source));
          +  -  +  -  +  
                +  -  - ]
    1280                 :             : 
    1281   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 2U);
                   +  - ]
    1282   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
                   +  - ]
    1283   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 1U);
                   +  - ]
    1284   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
                   +  - ]
    1285   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/true), 1U);
                   +  - ]
    1286   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/false), 1U);
                   +  - ]
    1287                 :             : 
    1288                 :             :     // add one i2p address to new
    1289         [ +  - ]:           1 :     CService i2p_addr;
    1290         [ +  - ]:           1 :     i2p_addr.SetSpecial("UDHDrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.I2P");
    1291                 :           1 :     const CAddress addr3{i2p_addr, NODE_NONE};
    1292   [ +  -  +  -  :           3 :     BOOST_CHECK(addrman->Add({addr3}, source));
          +  -  +  -  +  
                +  -  - ]
    1293   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/std::nullopt), 3U);
                   +  - ]
    1294   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_IPV4, /*in_new=*/std::nullopt), 2U);
                   +  - ]
    1295   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/std::nullopt), 1U);
                   +  - ]
    1296   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/NET_I2P, /*in_new=*/true), 1U);
                   +  - ]
    1297   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/true), 2U);
                   +  - ]
    1298   [ +  -  +  -  :           1 :     BOOST_CHECK_EQUAL(addrman->Size(/*net=*/std::nullopt, /*in_new=*/false), 1U);
                   +  - ]
    1299                 :           4 : }
    1300                 :             : 
    1301                 :             : BOOST_AUTO_TEST_SUITE_END()
        

Generated by: LCOV version 2.0-1