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