LCOV - code coverage report
Current view: top level - src/test - addrman_tests.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 0 707 0.0 %
Date: 2023-10-05 12:38:51 Functions: 0 121 0.0 %
Branches: 0 0 -

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

Generated by: LCOV version 1.14