LCOV - code coverage report
Current view: top level - src/test - addrman_tests.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 731 734 99.6 %
Date: 2026-06-25 07:23:43 Functions: 171 171 100.0 %

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

Generated by: LCOV version 1.16