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