Bitcoin Core  22.99.0
P2P Digital Currency
addrman_tests.cpp
Go to the documentation of this file.
1 // Copyright (c) 2012-2020 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 <chainparams.h>
8 #include <clientversion.h>
9 #include <hash.h>
10 #include <netbase.h>
11 #include <random.h>
12 #include <test/data/asmap.raw.h>
13 #include <test/util/setup_common.h>
14 #include <util/asmap.h>
15 #include <util/string.h>
16 
17 #include <boost/test/unit_test.hpp>
18 
19 #include <optional>
20 #include <string>
21 
22 using namespace std::literals;
23 
25 {
26 public:
27  virtual void Serialize(CDataStream& s) const = 0;
28 
30  : CAddrMan(/* asmap */ std::vector<bool>(), /* deterministic */ true, /* consistency_check_ratio */ 100)
31  {}
32 };
33 
35 {
36 public:
37  void Serialize(CDataStream& s) const override
38  {
40  }
41 };
42 
44 {
45 public:
46  void Serialize(CDataStream& s) const override
47  {
48  // Produces corrupt output that claims addrman has 20 addrs when it only has one addr.
49  unsigned char nVersion = 1;
50  s << nVersion;
51  s << ((unsigned char)32);
52  s << uint256::ONE;
53  s << 10; // nNew
54  s << 10; // nTried
55 
56  int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
57  s << nUBuckets;
58 
59  CService serv;
60  BOOST_CHECK(Lookup("252.1.1.1", serv, 7777, false));
61  CAddress addr = CAddress(serv, NODE_NONE);
62  CNetAddr resolved;
63  BOOST_CHECK(LookupHost("252.2.2.2", resolved, false));
64  CAddrInfo info = CAddrInfo(addr, resolved);
65  s << info;
66  }
67 };
68 
70 {
72  ssPeersIn << Params().MessageStart();
73  ssPeersIn << _addrman;
74  std::string str = ssPeersIn.str();
75  std::vector<unsigned char> vchData(str.begin(), str.end());
76  return CDataStream(vchData, SER_DISK, CLIENT_VERSION);
77 }
78 
79 class CAddrManTest : public CAddrMan
80 {
81 private:
83 public:
84  explicit CAddrManTest(bool makeDeterministic = true,
85  std::vector<bool> asmap = std::vector<bool>())
86  : CAddrMan(asmap, makeDeterministic, /* consistency_check_ratio */ 100)
87  {
88  deterministic = makeDeterministic;
89  }
90 
91  CAddrInfo* Find(const CNetAddr& addr, int* pnId = nullptr)
92  {
93  LOCK(cs);
94  return CAddrMan::Find(addr, pnId);
95  }
96 
97  CAddrInfo* Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId = nullptr)
98  {
99  LOCK(cs);
100  return CAddrMan::Create(addr, addrSource, pnId);
101  }
102 
103  void Delete(int nId)
104  {
105  LOCK(cs);
106  CAddrMan::Delete(nId);
107  }
108 
109  // Used to test deserialization
110  std::pair<int, int> GetBucketAndEntry(const CAddress& addr)
111  {
112  LOCK(cs);
113  int nId = mapAddr[addr];
114  for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; ++bucket) {
115  for (int entry = 0; entry < ADDRMAN_BUCKET_SIZE; ++entry) {
116  if (nId == vvNew[bucket][entry]) {
117  return std::pair<int, int>(bucket, entry);
118  }
119  }
120  }
121  return std::pair<int, int>(-1, -1);
122  }
123 
124  // Simulates connection failure so that we can test eviction of offline nodes
125  void SimConnFail(const CService& addr)
126  {
127  int64_t nLastSuccess = 1;
128  // Set last good connection in the deep past.
129  Good(addr, nLastSuccess);
130 
131  bool count_failure = false;
132  int64_t nLastTry = GetAdjustedTime()-61;
133  Attempt(addr, count_failure, nLastTry);
134  }
135 };
136 
137 static CNetAddr ResolveIP(const std::string& ip)
138 {
139  CNetAddr addr;
140  BOOST_CHECK_MESSAGE(LookupHost(ip, addr, false), strprintf("failed to resolve: %s", ip));
141  return addr;
142 }
143 
144 static CService ResolveService(const std::string& ip, uint16_t port = 0)
145 {
146  CService serv;
147  BOOST_CHECK_MESSAGE(Lookup(ip, serv, port, false), strprintf("failed to resolve: %s:%i", ip, port));
148  return serv;
149 }
150 
151 
152 static std::vector<bool> FromBytes(const unsigned char* source, int vector_size) {
153  std::vector<bool> result(vector_size);
154  for (int byte_i = 0; byte_i < vector_size / 8; ++byte_i) {
155  unsigned char cur_byte = source[byte_i];
156  for (int bit_i = 0; bit_i < 8; ++bit_i) {
157  result[byte_i * 8 + bit_i] = (cur_byte >> bit_i) & 1;
158  }
159  }
160  return result;
161 }
162 
163 
165 
166 BOOST_AUTO_TEST_CASE(addrman_simple)
167 {
168  auto addrman = std::make_unique<CAddrManTest>();
169 
170  CNetAddr source = ResolveIP("252.2.2.2");
171 
172  // Test: Does Addrman respond correctly when empty.
173  BOOST_CHECK_EQUAL(addrman->size(), 0U);
174  CAddrInfo addr_null = addrman->Select();
175  BOOST_CHECK_EQUAL(addr_null.ToString(), "[::]:0");
176 
177  // Test: Does Addrman::Add work as expected.
178  CService addr1 = ResolveService("250.1.1.1", 8333);
179  BOOST_CHECK(addrman->Add({CAddress(addr1, NODE_NONE)}, source));
180  BOOST_CHECK_EQUAL(addrman->size(), 1U);
181  CAddrInfo addr_ret1 = addrman->Select();
182  BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
183 
184  // Test: Does IP address deduplication work correctly.
185  // Expected dup IP should not be added.
186  CService addr1_dup = ResolveService("250.1.1.1", 8333);
187  BOOST_CHECK(!addrman->Add({CAddress(addr1_dup, NODE_NONE)}, source));
188  BOOST_CHECK_EQUAL(addrman->size(), 1U);
189 
190 
191  // Test: New table has one addr and we add a diff addr we should
192  // have at least one addr.
193  // Note that addrman's size cannot be tested reliably after insertion, as
194  // hash collisions may occur. But we can always be sure of at least one
195  // success.
196 
197  CService addr2 = ResolveService("250.1.1.2", 8333);
198  BOOST_CHECK(addrman->Add({CAddress(addr2, NODE_NONE)}, source));
199  BOOST_CHECK(addrman->size() >= 1);
200 
201  // Test: reset addrman and test AddrMan::Add multiple addresses works as expected
202  addrman = std::make_unique<CAddrManTest>();
203  std::vector<CAddress> vAddr;
204  vAddr.push_back(CAddress(ResolveService("250.1.1.3", 8333), NODE_NONE));
205  vAddr.push_back(CAddress(ResolveService("250.1.1.4", 8333), NODE_NONE));
206  BOOST_CHECK(addrman->Add(vAddr, source));
207  BOOST_CHECK(addrman->size() >= 1);
208 }
209 
210 BOOST_AUTO_TEST_CASE(addrman_ports)
211 {
212  CAddrManTest addrman;
213 
214  CNetAddr source = ResolveIP("252.2.2.2");
215 
216  BOOST_CHECK_EQUAL(addrman.size(), 0U);
217 
218  // Test 7; Addr with same IP but diff port does not replace existing addr.
219  CService addr1 = ResolveService("250.1.1.1", 8333);
220  BOOST_CHECK(addrman.Add({CAddress(addr1, NODE_NONE)}, source));
221  BOOST_CHECK_EQUAL(addrman.size(), 1U);
222 
223  CService addr1_port = ResolveService("250.1.1.1", 8334);
224  BOOST_CHECK(!addrman.Add({CAddress(addr1_port, NODE_NONE)}, source));
225  BOOST_CHECK_EQUAL(addrman.size(), 1U);
226  CAddrInfo addr_ret2 = addrman.Select();
227  BOOST_CHECK_EQUAL(addr_ret2.ToString(), "250.1.1.1:8333");
228 
229  // Test: Add same IP but diff port to tried table, it doesn't get added.
230  // Perhaps this is not ideal behavior but it is the current behavior.
231  addrman.Good(CAddress(addr1_port, NODE_NONE));
232  BOOST_CHECK_EQUAL(addrman.size(), 1U);
233  bool newOnly = true;
234  CAddrInfo addr_ret3 = addrman.Select(newOnly);
235  BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
236 }
237 
238 
239 BOOST_AUTO_TEST_CASE(addrman_select)
240 {
241  CAddrManTest addrman;
242 
243  CNetAddr source = ResolveIP("252.2.2.2");
244 
245  // Test: Select from new with 1 addr in new.
246  CService addr1 = ResolveService("250.1.1.1", 8333);
247  BOOST_CHECK(addrman.Add({CAddress(addr1, NODE_NONE)}, source));
248  BOOST_CHECK_EQUAL(addrman.size(), 1U);
249 
250  bool newOnly = true;
251  CAddrInfo addr_ret1 = addrman.Select(newOnly);
252  BOOST_CHECK_EQUAL(addr_ret1.ToString(), "250.1.1.1:8333");
253 
254  // Test: move addr to tried, select from new expected nothing returned.
255  addrman.Good(CAddress(addr1, NODE_NONE));
256  BOOST_CHECK_EQUAL(addrman.size(), 1U);
257  CAddrInfo addr_ret2 = addrman.Select(newOnly);
258  BOOST_CHECK_EQUAL(addr_ret2.ToString(), "[::]:0");
259 
260  CAddrInfo addr_ret3 = addrman.Select();
261  BOOST_CHECK_EQUAL(addr_ret3.ToString(), "250.1.1.1:8333");
262 
263  BOOST_CHECK_EQUAL(addrman.size(), 1U);
264 
265 
266  // Add three addresses to new table.
267  CService addr2 = ResolveService("250.3.1.1", 8333);
268  CService addr3 = ResolveService("250.3.2.2", 9999);
269  CService addr4 = ResolveService("250.3.3.3", 9999);
270 
271  BOOST_CHECK(addrman.Add({CAddress(addr2, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
272  BOOST_CHECK(addrman.Add({CAddress(addr3, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
273  BOOST_CHECK(addrman.Add({CAddress(addr4, NODE_NONE)}, ResolveService("250.4.1.1", 8333)));
274 
275  // Add three addresses to tried table.
276  CService addr5 = ResolveService("250.4.4.4", 8333);
277  CService addr6 = ResolveService("250.4.5.5", 7777);
278  CService addr7 = ResolveService("250.4.6.6", 8333);
279 
280  BOOST_CHECK(addrman.Add({CAddress(addr5, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
281  addrman.Good(CAddress(addr5, NODE_NONE));
282  BOOST_CHECK(addrman.Add({CAddress(addr6, NODE_NONE)}, ResolveService("250.3.1.1", 8333)));
283  addrman.Good(CAddress(addr6, NODE_NONE));
284  BOOST_CHECK(addrman.Add({CAddress(addr7, NODE_NONE)}, ResolveService("250.1.1.3", 8333)));
285  addrman.Good(CAddress(addr7, NODE_NONE));
286 
287  // Test: 6 addrs + 1 addr from last test = 7.
288  BOOST_CHECK_EQUAL(addrman.size(), 7U);
289 
290  // Test: Select pulls from new and tried regardless of port number.
291  std::set<uint16_t> ports;
292  for (int i = 0; i < 20; ++i) {
293  ports.insert(addrman.Select().GetPort());
294  }
295  BOOST_CHECK_EQUAL(ports.size(), 3U);
296 }
297 
298 BOOST_AUTO_TEST_CASE(addrman_new_collisions)
299 {
300  CAddrManTest addrman;
301 
302  CNetAddr source = ResolveIP("252.2.2.2");
303 
304  uint32_t num_addrs{0};
305 
306  BOOST_CHECK_EQUAL(addrman.size(), num_addrs);
307 
308  while (num_addrs < 22) { // Magic number! 250.1.1.1 - 250.1.1.22 do not collide with deterministic key = 1
309  CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
310  BOOST_CHECK(addrman.Add({CAddress(addr, NODE_NONE)}, source));
311 
312  //Test: No collision in new table yet.
313  BOOST_CHECK_EQUAL(addrman.size(), num_addrs);
314  }
315 
316  //Test: new table collision!
317  CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
318  uint32_t collisions{1};
319  BOOST_CHECK(addrman.Add({CAddress(addr1, NODE_NONE)}, source));
320  BOOST_CHECK_EQUAL(addrman.size(), num_addrs - collisions);
321 
322  CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
323  BOOST_CHECK(addrman.Add({CAddress(addr2, NODE_NONE)}, source));
324  BOOST_CHECK_EQUAL(addrman.size(), num_addrs - collisions);
325 }
326 
327 BOOST_AUTO_TEST_CASE(addrman_tried_collisions)
328 {
329  CAddrManTest addrman;
330 
331  CNetAddr source = ResolveIP("252.2.2.2");
332 
333  uint32_t num_addrs{0};
334 
335  BOOST_CHECK_EQUAL(addrman.size(), num_addrs);
336 
337  while (num_addrs < 64) { // Magic number! 250.1.1.1 - 250.1.1.64 do not collide with deterministic key = 1
338  CService addr = ResolveService("250.1.1." + ToString(++num_addrs));
339  BOOST_CHECK(addrman.Add({CAddress(addr, NODE_NONE)}, source));
340  addrman.Good(CAddress(addr, NODE_NONE));
341 
342  //Test: No collision in tried table yet.
343  BOOST_CHECK_EQUAL(addrman.size(), num_addrs);
344  }
345 
346  //Test: tried table collision!
347  CService addr1 = ResolveService("250.1.1." + ToString(++num_addrs));
348  uint32_t collisions{1};
349  BOOST_CHECK(addrman.Add({CAddress(addr1, NODE_NONE)}, source));
350  BOOST_CHECK_EQUAL(addrman.size(), num_addrs - collisions);
351 
352  CService addr2 = ResolveService("250.1.1." + ToString(++num_addrs));
353  BOOST_CHECK(addrman.Add({CAddress(addr2, NODE_NONE)}, source));
354  BOOST_CHECK_EQUAL(addrman.size(), num_addrs - collisions);
355 }
356 
357 BOOST_AUTO_TEST_CASE(addrman_find)
358 {
359  CAddrManTest addrman;
360 
361  BOOST_CHECK_EQUAL(addrman.size(), 0U);
362 
363  CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
364  CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
365  CAddress addr3 = CAddress(ResolveService("251.255.2.1", 8333), NODE_NONE);
366 
367  CNetAddr source1 = ResolveIP("250.1.2.1");
368  CNetAddr source2 = ResolveIP("250.1.2.2");
369 
370  BOOST_CHECK(addrman.Add({addr1}, source1));
371  BOOST_CHECK(!addrman.Add({addr2}, source2));
372  BOOST_CHECK(addrman.Add({addr3}, source1));
373 
374  // Test: ensure Find returns an IP matching what we searched on.
375  CAddrInfo* info1 = addrman.Find(addr1);
376  BOOST_REQUIRE(info1);
377  BOOST_CHECK_EQUAL(info1->ToString(), "250.1.2.1:8333");
378 
379  // Test 18; Find does not discriminate by port number.
380  CAddrInfo* info2 = addrman.Find(addr2);
381  BOOST_REQUIRE(info2);
382  BOOST_CHECK_EQUAL(info2->ToString(), info1->ToString());
383 
384  // Test: Find returns another IP matching what we searched on.
385  CAddrInfo* info3 = addrman.Find(addr3);
386  BOOST_REQUIRE(info3);
387  BOOST_CHECK_EQUAL(info3->ToString(), "251.255.2.1:8333");
388 }
389 
390 BOOST_AUTO_TEST_CASE(addrman_create)
391 {
392  CAddrManTest addrman;
393 
394  BOOST_CHECK_EQUAL(addrman.size(), 0U);
395 
396  CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
397  CNetAddr source1 = ResolveIP("250.1.2.1");
398 
399  int nId;
400  CAddrInfo* pinfo = addrman.Create(addr1, source1, &nId);
401 
402  // Test: The result should be the same as the input addr.
403  BOOST_CHECK_EQUAL(pinfo->ToString(), "250.1.2.1:8333");
404 
405  CAddrInfo* info2 = addrman.Find(addr1);
406  BOOST_CHECK_EQUAL(info2->ToString(), "250.1.2.1:8333");
407 }
408 
409 
410 BOOST_AUTO_TEST_CASE(addrman_delete)
411 {
412  CAddrManTest addrman;
413 
414  BOOST_CHECK_EQUAL(addrman.size(), 0U);
415 
416  CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
417  CNetAddr source1 = ResolveIP("250.1.2.1");
418 
419  int nId;
420  addrman.Create(addr1, source1, &nId);
421 
422  // Test: Delete should actually delete the addr.
423  BOOST_CHECK_EQUAL(addrman.size(), 1U);
424  addrman.Delete(nId);
425  BOOST_CHECK_EQUAL(addrman.size(), 0U);
426  CAddrInfo* info2 = addrman.Find(addr1);
427  BOOST_CHECK(info2 == nullptr);
428 }
429 
430 BOOST_AUTO_TEST_CASE(addrman_getaddr)
431 {
432  CAddrManTest addrman;
433 
434  // Test: Sanity check, GetAddr should never return anything if addrman
435  // is empty.
436  BOOST_CHECK_EQUAL(addrman.size(), 0U);
437  std::vector<CAddress> vAddr1 = addrman.GetAddr(/* max_addresses */ 0, /* max_pct */ 0, /* network */ std::nullopt);
438  BOOST_CHECK_EQUAL(vAddr1.size(), 0U);
439 
440  CAddress addr1 = CAddress(ResolveService("250.250.2.1", 8333), NODE_NONE);
441  addr1.nTime = GetAdjustedTime(); // Set time so isTerrible = false
442  CAddress addr2 = CAddress(ResolveService("250.251.2.2", 9999), NODE_NONE);
443  addr2.nTime = GetAdjustedTime();
444  CAddress addr3 = CAddress(ResolveService("251.252.2.3", 8333), NODE_NONE);
445  addr3.nTime = GetAdjustedTime();
446  CAddress addr4 = CAddress(ResolveService("252.253.3.4", 8333), NODE_NONE);
447  addr4.nTime = GetAdjustedTime();
448  CAddress addr5 = CAddress(ResolveService("252.254.4.5", 8333), NODE_NONE);
449  addr5.nTime = GetAdjustedTime();
450  CNetAddr source1 = ResolveIP("250.1.2.1");
451  CNetAddr source2 = ResolveIP("250.2.3.3");
452 
453  // Test: Ensure GetAddr works with new addresses.
454  BOOST_CHECK(addrman.Add({addr1, addr3, addr5}, source1));
455  BOOST_CHECK(addrman.Add({addr2, addr4}, source2));
456 
457  BOOST_CHECK_EQUAL(addrman.GetAddr(/* max_addresses */ 0, /* max_pct */ 0, /* network */ std::nullopt).size(), 5U);
458  // Net processing asks for 23% of addresses. 23% of 5 is 1 rounded down.
459  BOOST_CHECK_EQUAL(addrman.GetAddr(/* max_addresses */ 2500, /* max_pct */ 23, /* network */ std::nullopt).size(), 1U);
460 
461  // Test: Ensure GetAddr works with new and tried addresses.
462  addrman.Good(CAddress(addr1, NODE_NONE));
463  addrman.Good(CAddress(addr2, NODE_NONE));
464  BOOST_CHECK_EQUAL(addrman.GetAddr(/* max_addresses */ 0, /* max_pct */ 0, /* network */ std::nullopt).size(), 5U);
465  BOOST_CHECK_EQUAL(addrman.GetAddr(/* max_addresses */ 2500, /* max_pct */ 23, /* network */ std::nullopt).size(), 1U);
466 
467  // Test: Ensure GetAddr still returns 23% when addrman has many addrs.
468  for (unsigned int i = 1; i < (8 * 256); i++) {
469  int octet1 = i % 256;
470  int octet2 = i >> 8 % 256;
471  std::string strAddr = ToString(octet1) + "." + ToString(octet2) + ".1.23";
472  CAddress addr = CAddress(ResolveService(strAddr), NODE_NONE);
473 
474  // Ensure that for all addrs in addrman, isTerrible == false.
475  addr.nTime = GetAdjustedTime();
476  addrman.Add({addr}, ResolveIP(strAddr));
477  if (i % 8 == 0)
478  addrman.Good(addr);
479  }
480  std::vector<CAddress> vAddr = addrman.GetAddr(/* max_addresses */ 2500, /* max_pct */ 23, /* network */ std::nullopt);
481 
482  size_t percent23 = (addrman.size() * 23) / 100;
483  BOOST_CHECK_EQUAL(vAddr.size(), percent23);
484  BOOST_CHECK_EQUAL(vAddr.size(), 461U);
485  // (Addrman.size() < number of addresses added) due to address collisions.
486  BOOST_CHECK_EQUAL(addrman.size(), 2006U);
487 }
488 
489 
490 BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket_legacy)
491 {
492  CAddrManTest addrman;
493 
494  CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
495  CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
496 
497  CNetAddr source1 = ResolveIP("250.1.1.1");
498 
499 
500  CAddrInfo info1 = CAddrInfo(addr1, source1);
501 
502  uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
503  uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
504 
505  std::vector<bool> asmap; // use /16
506 
507  BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, asmap), 40);
508 
509  // Test: Make sure key actually randomizes bucket placement. A fail on
510  // this test could be a security issue.
511  BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info1.GetTriedBucket(nKey2, asmap));
512 
513  // Test: Two addresses with same IP but different ports can map to
514  // different buckets because they have different keys.
515  CAddrInfo info2 = CAddrInfo(addr2, source1);
516 
517  BOOST_CHECK(info1.GetKey() != info2.GetKey());
518  BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info2.GetTriedBucket(nKey1, asmap));
519 
520  std::set<int> buckets;
521  for (int i = 0; i < 255; i++) {
522  CAddrInfo infoi = CAddrInfo(
523  CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
524  ResolveIP("250.1.1." + ToString(i)));
525  int bucket = infoi.GetTriedBucket(nKey1, asmap);
526  buckets.insert(bucket);
527  }
528  // Test: IP addresses in the same /16 prefix should
529  // never get more than 8 buckets with legacy grouping
530  BOOST_CHECK_EQUAL(buckets.size(), 8U);
531 
532  buckets.clear();
533  for (int j = 0; j < 255; j++) {
534  CAddrInfo infoj = CAddrInfo(
535  CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
536  ResolveIP("250." + ToString(j) + ".1.1"));
537  int bucket = infoj.GetTriedBucket(nKey1, asmap);
538  buckets.insert(bucket);
539  }
540  // Test: IP addresses in the different /16 prefix should map to more than
541  // 8 buckets with legacy grouping
542  BOOST_CHECK_EQUAL(buckets.size(), 160U);
543 }
544 
545 BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket_legacy)
546 {
547  CAddrManTest addrman;
548 
549  CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
550  CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
551 
552  CNetAddr source1 = ResolveIP("250.1.2.1");
553 
554  CAddrInfo info1 = CAddrInfo(addr1, source1);
555 
556  uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
557  uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
558 
559  std::vector<bool> asmap; // use /16
560 
561  // Test: Make sure the buckets are what we expect
562  BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), 786);
563  BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, asmap), 786);
564 
565  // Test: Make sure key actually randomizes bucket placement. A fail on
566  // this test could be a security issue.
567  BOOST_CHECK(info1.GetNewBucket(nKey1, asmap) != info1.GetNewBucket(nKey2, asmap));
568 
569  // Test: Ports should not affect bucket placement in the addr
570  CAddrInfo info2 = CAddrInfo(addr2, source1);
571  BOOST_CHECK(info1.GetKey() != info2.GetKey());
572  BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), info2.GetNewBucket(nKey1, asmap));
573 
574  std::set<int> buckets;
575  for (int i = 0; i < 255; i++) {
576  CAddrInfo infoi = CAddrInfo(
577  CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
578  ResolveIP("250.1.1." + ToString(i)));
579  int bucket = infoi.GetNewBucket(nKey1, asmap);
580  buckets.insert(bucket);
581  }
582  // Test: IP addresses in the same group (\16 prefix for IPv4) should
583  // always map to the same bucket.
584  BOOST_CHECK_EQUAL(buckets.size(), 1U);
585 
586  buckets.clear();
587  for (int j = 0; j < 4 * 255; j++) {
588  CAddrInfo infoj = CAddrInfo(CAddress(
590  ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
591  ResolveIP("251.4.1.1"));
592  int bucket = infoj.GetNewBucket(nKey1, asmap);
593  buckets.insert(bucket);
594  }
595  // Test: IP addresses in the same source groups should map to NO MORE
596  // than 64 buckets.
597  BOOST_CHECK(buckets.size() <= 64);
598 
599  buckets.clear();
600  for (int p = 0; p < 255; p++) {
601  CAddrInfo infoj = CAddrInfo(
602  CAddress(ResolveService("250.1.1.1"), NODE_NONE),
603  ResolveIP("250." + ToString(p) + ".1.1"));
604  int bucket = infoj.GetNewBucket(nKey1, asmap);
605  buckets.insert(bucket);
606  }
607  // Test: IP addresses in the different source groups should map to MORE
608  // than 64 buckets.
609  BOOST_CHECK(buckets.size() > 64);
610 }
611 
612 // The following three test cases use asmap.raw
613 // We use an artificial minimal mock mapping
614 // 250.0.0.0/8 AS1000
615 // 101.1.0.0/16 AS1
616 // 101.2.0.0/16 AS2
617 // 101.3.0.0/16 AS3
618 // 101.4.0.0/16 AS4
619 // 101.5.0.0/16 AS5
620 // 101.6.0.0/16 AS6
621 // 101.7.0.0/16 AS7
622 // 101.8.0.0/16 AS8
623 BOOST_AUTO_TEST_CASE(caddrinfo_get_tried_bucket)
624 {
625  CAddrManTest addrman;
626 
627  CAddress addr1 = CAddress(ResolveService("250.1.1.1", 8333), NODE_NONE);
628  CAddress addr2 = CAddress(ResolveService("250.1.1.1", 9999), NODE_NONE);
629 
630  CNetAddr source1 = ResolveIP("250.1.1.1");
631 
632 
633  CAddrInfo info1 = CAddrInfo(addr1, source1);
634 
635  uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
636  uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
637 
638  std::vector<bool> asmap = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
639 
640  BOOST_CHECK_EQUAL(info1.GetTriedBucket(nKey1, asmap), 236);
641 
642  // Test: Make sure key actually randomizes bucket placement. A fail on
643  // this test could be a security issue.
644  BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info1.GetTriedBucket(nKey2, asmap));
645 
646  // Test: Two addresses with same IP but different ports can map to
647  // different buckets because they have different keys.
648  CAddrInfo info2 = CAddrInfo(addr2, source1);
649 
650  BOOST_CHECK(info1.GetKey() != info2.GetKey());
651  BOOST_CHECK(info1.GetTriedBucket(nKey1, asmap) != info2.GetTriedBucket(nKey1, asmap));
652 
653  std::set<int> buckets;
654  for (int j = 0; j < 255; j++) {
655  CAddrInfo infoj = CAddrInfo(
656  CAddress(ResolveService("101." + ToString(j) + ".1.1"), NODE_NONE),
657  ResolveIP("101." + ToString(j) + ".1.1"));
658  int bucket = infoj.GetTriedBucket(nKey1, asmap);
659  buckets.insert(bucket);
660  }
661  // Test: IP addresses in the different /16 prefix MAY map to more than
662  // 8 buckets.
663  BOOST_CHECK(buckets.size() > 8);
664 
665  buckets.clear();
666  for (int j = 0; j < 255; j++) {
667  CAddrInfo infoj = CAddrInfo(
668  CAddress(ResolveService("250." + ToString(j) + ".1.1"), NODE_NONE),
669  ResolveIP("250." + ToString(j) + ".1.1"));
670  int bucket = infoj.GetTriedBucket(nKey1, asmap);
671  buckets.insert(bucket);
672  }
673  // Test: IP addresses in the different /16 prefix MAY NOT map to more than
674  // 8 buckets.
675  BOOST_CHECK(buckets.size() == 8);
676 }
677 
678 BOOST_AUTO_TEST_CASE(caddrinfo_get_new_bucket)
679 {
680  CAddrManTest addrman;
681 
682  CAddress addr1 = CAddress(ResolveService("250.1.2.1", 8333), NODE_NONE);
683  CAddress addr2 = CAddress(ResolveService("250.1.2.1", 9999), NODE_NONE);
684 
685  CNetAddr source1 = ResolveIP("250.1.2.1");
686 
687  CAddrInfo info1 = CAddrInfo(addr1, source1);
688 
689  uint256 nKey1 = (uint256)(CHashWriter(SER_GETHASH, 0) << 1).GetHash();
690  uint256 nKey2 = (uint256)(CHashWriter(SER_GETHASH, 0) << 2).GetHash();
691 
692  std::vector<bool> asmap = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
693 
694  // Test: Make sure the buckets are what we expect
695  BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), 795);
696  BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, source1, asmap), 795);
697 
698  // Test: Make sure key actually randomizes bucket placement. A fail on
699  // this test could be a security issue.
700  BOOST_CHECK(info1.GetNewBucket(nKey1, asmap) != info1.GetNewBucket(nKey2, asmap));
701 
702  // Test: Ports should not affect bucket placement in the addr
703  CAddrInfo info2 = CAddrInfo(addr2, source1);
704  BOOST_CHECK(info1.GetKey() != info2.GetKey());
705  BOOST_CHECK_EQUAL(info1.GetNewBucket(nKey1, asmap), info2.GetNewBucket(nKey1, asmap));
706 
707  std::set<int> buckets;
708  for (int i = 0; i < 255; i++) {
709  CAddrInfo infoi = CAddrInfo(
710  CAddress(ResolveService("250.1.1." + ToString(i)), NODE_NONE),
711  ResolveIP("250.1.1." + ToString(i)));
712  int bucket = infoi.GetNewBucket(nKey1, asmap);
713  buckets.insert(bucket);
714  }
715  // Test: IP addresses in the same /16 prefix
716  // usually map to the same bucket.
717  BOOST_CHECK_EQUAL(buckets.size(), 1U);
718 
719  buckets.clear();
720  for (int j = 0; j < 4 * 255; j++) {
721  CAddrInfo infoj = CAddrInfo(CAddress(
723  ToString(250 + (j / 255)) + "." + ToString(j % 256) + ".1.1"), NODE_NONE),
724  ResolveIP("251.4.1.1"));
725  int bucket = infoj.GetNewBucket(nKey1, asmap);
726  buckets.insert(bucket);
727  }
728  // Test: IP addresses in the same source /16 prefix should not map to more
729  // than 64 buckets.
730  BOOST_CHECK(buckets.size() <= 64);
731 
732  buckets.clear();
733  for (int p = 0; p < 255; p++) {
734  CAddrInfo infoj = CAddrInfo(
735  CAddress(ResolveService("250.1.1.1"), NODE_NONE),
736  ResolveIP("101." + ToString(p) + ".1.1"));
737  int bucket = infoj.GetNewBucket(nKey1, asmap);
738  buckets.insert(bucket);
739  }
740  // Test: IP addresses in the different source /16 prefixes usually map to MORE
741  // than 1 bucket.
742  BOOST_CHECK(buckets.size() > 1);
743 
744  buckets.clear();
745  for (int p = 0; p < 255; p++) {
746  CAddrInfo infoj = CAddrInfo(
747  CAddress(ResolveService("250.1.1.1"), NODE_NONE),
748  ResolveIP("250." + ToString(p) + ".1.1"));
749  int bucket = infoj.GetNewBucket(nKey1, asmap);
750  buckets.insert(bucket);
751  }
752  // Test: IP addresses in the different source /16 prefixes sometimes map to NO MORE
753  // than 1 bucket.
754  BOOST_CHECK(buckets.size() == 1);
755 
756 }
757 
758 BOOST_AUTO_TEST_CASE(addrman_serialization)
759 {
760  std::vector<bool> asmap1 = FromBytes(asmap_raw, sizeof(asmap_raw) * 8);
761 
762  auto addrman_asmap1 = std::make_unique<CAddrManTest>(true, asmap1);
763  auto addrman_asmap1_dup = std::make_unique<CAddrManTest>(true, asmap1);
764  auto addrman_noasmap = std::make_unique<CAddrManTest>();
766 
767  CAddress addr = CAddress(ResolveService("250.1.1.1"), NODE_NONE);
768  CNetAddr default_source;
769 
770 
771  addrman_asmap1->Add({addr}, default_source);
772 
773  stream << *addrman_asmap1;
774  // serizalizing/deserializing addrman with the same asmap
775  stream >> *addrman_asmap1_dup;
776 
777  std::pair<int, int> bucketAndEntry_asmap1 = addrman_asmap1->GetBucketAndEntry(addr);
778  std::pair<int, int> bucketAndEntry_asmap1_dup = addrman_asmap1_dup->GetBucketAndEntry(addr);
779  BOOST_CHECK(bucketAndEntry_asmap1.second != -1);
780  BOOST_CHECK(bucketAndEntry_asmap1_dup.second != -1);
781 
782  BOOST_CHECK(bucketAndEntry_asmap1.first == bucketAndEntry_asmap1_dup.first);
783  BOOST_CHECK(bucketAndEntry_asmap1.second == bucketAndEntry_asmap1_dup.second);
784 
785  // deserializing asmaped peers.dat to non-asmaped addrman
786  stream << *addrman_asmap1;
787  stream >> *addrman_noasmap;
788  std::pair<int, int> bucketAndEntry_noasmap = addrman_noasmap->GetBucketAndEntry(addr);
789  BOOST_CHECK(bucketAndEntry_noasmap.second != -1);
790  BOOST_CHECK(bucketAndEntry_asmap1.first != bucketAndEntry_noasmap.first);
791  BOOST_CHECK(bucketAndEntry_asmap1.second != bucketAndEntry_noasmap.second);
792 
793  // deserializing non-asmaped peers.dat to asmaped addrman
794  addrman_asmap1 = std::make_unique<CAddrManTest>(true, asmap1);
795  addrman_noasmap = std::make_unique<CAddrManTest>();
796  addrman_noasmap->Add({addr}, default_source);
797  stream << *addrman_noasmap;
798  stream >> *addrman_asmap1;
799  std::pair<int, int> bucketAndEntry_asmap1_deser = addrman_asmap1->GetBucketAndEntry(addr);
800  BOOST_CHECK(bucketAndEntry_asmap1_deser.second != -1);
801  BOOST_CHECK(bucketAndEntry_asmap1_deser.first != bucketAndEntry_noasmap.first);
802  BOOST_CHECK(bucketAndEntry_asmap1_deser.first == bucketAndEntry_asmap1_dup.first);
803  BOOST_CHECK(bucketAndEntry_asmap1_deser.second == bucketAndEntry_asmap1_dup.second);
804 
805  // used to map to different buckets, now maps to the same bucket.
806  addrman_asmap1 = std::make_unique<CAddrManTest>(true, asmap1);
807  addrman_noasmap = std::make_unique<CAddrManTest>();
810  addrman_noasmap->Add({addr, addr2}, default_source);
811  std::pair<int, int> bucketAndEntry_noasmap_addr1 = addrman_noasmap->GetBucketAndEntry(addr1);
812  std::pair<int, int> bucketAndEntry_noasmap_addr2 = addrman_noasmap->GetBucketAndEntry(addr2);
813  BOOST_CHECK(bucketAndEntry_noasmap_addr1.first != bucketAndEntry_noasmap_addr2.first);
814  BOOST_CHECK(bucketAndEntry_noasmap_addr1.second != bucketAndEntry_noasmap_addr2.second);
815  stream << *addrman_noasmap;
816  stream >> *addrman_asmap1;
817  std::pair<int, int> bucketAndEntry_asmap1_deser_addr1 = addrman_asmap1->GetBucketAndEntry(addr1);
818  std::pair<int, int> bucketAndEntry_asmap1_deser_addr2 = addrman_asmap1->GetBucketAndEntry(addr2);
819  BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.first == bucketAndEntry_asmap1_deser_addr2.first);
820  BOOST_CHECK(bucketAndEntry_asmap1_deser_addr1.second != bucketAndEntry_asmap1_deser_addr2.second);
821 }
822 
823 BOOST_AUTO_TEST_CASE(remove_invalid)
824 {
825  // Confirm that invalid addresses are ignored in unserialization.
826 
827  auto addrman = std::make_unique<CAddrManTest>();
829 
830  const CAddress new1{ResolveService("5.5.5.5"), NODE_NONE};
831  const CAddress new2{ResolveService("6.6.6.6"), NODE_NONE};
832  const CAddress tried1{ResolveService("7.7.7.7"), NODE_NONE};
833  const CAddress tried2{ResolveService("8.8.8.8"), NODE_NONE};
834 
835  addrman->Add({new1, tried1, new2, tried2}, CNetAddr{});
836  addrman->Good(tried1);
837  addrman->Good(tried2);
838  BOOST_REQUIRE_EQUAL(addrman->size(), 4);
839 
840  stream << *addrman;
841 
842  const std::string str{stream.str()};
843  size_t pos;
844 
845  const char new2_raw[]{6, 6, 6, 6};
846  const uint8_t new2_raw_replacement[]{0, 0, 0, 0}; // 0.0.0.0 is !IsValid()
847  pos = str.find(new2_raw, 0, sizeof(new2_raw));
848  BOOST_REQUIRE(pos != std::string::npos);
849  BOOST_REQUIRE(pos + sizeof(new2_raw_replacement) <= stream.size());
850  memcpy(stream.data() + pos, new2_raw_replacement, sizeof(new2_raw_replacement));
851 
852  const char tried2_raw[]{8, 8, 8, 8};
853  const uint8_t tried2_raw_replacement[]{255, 255, 255, 255}; // 255.255.255.255 is !IsValid()
854  pos = str.find(tried2_raw, 0, sizeof(tried2_raw));
855  BOOST_REQUIRE(pos != std::string::npos);
856  BOOST_REQUIRE(pos + sizeof(tried2_raw_replacement) <= stream.size());
857  memcpy(stream.data() + pos, tried2_raw_replacement, sizeof(tried2_raw_replacement));
858 
859  addrman = std::make_unique<CAddrManTest>();
860  stream >> *addrman;
861  BOOST_CHECK_EQUAL(addrman->size(), 2);
862 }
863 
864 BOOST_AUTO_TEST_CASE(addrman_selecttriedcollision)
865 {
866  CAddrManTest addrman;
867 
868  BOOST_CHECK(addrman.size() == 0);
869 
870  // Empty addrman should return blank addrman info.
871  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
872 
873  // Add twenty two addresses.
874  CNetAddr source = ResolveIP("252.2.2.2");
875  for (unsigned int i = 1; i < 23; i++) {
876  CService addr = ResolveService("250.1.1."+ToString(i));
877  BOOST_CHECK(addrman.Add({CAddress(addr, NODE_NONE)}, source));
878  addrman.Good(addr);
879 
880  // No collisions yet.
881  BOOST_CHECK(addrman.size() == i);
882  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
883  }
884 
885  // Ensure Good handles duplicates well.
886  for (unsigned int i = 1; i < 23; i++) {
887  CService addr = ResolveService("250.1.1."+ToString(i));
888  addrman.Good(addr);
889 
890  BOOST_CHECK(addrman.size() == 22);
891  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
892  }
893 
894 }
895 
896 BOOST_AUTO_TEST_CASE(addrman_noevict)
897 {
898  CAddrManTest addrman;
899 
900  // Add 35 addresses.
901  CNetAddr source = ResolveIP("252.2.2.2");
902  for (unsigned int i = 1; i < 36; i++) {
903  CService addr = ResolveService("250.1.1."+ToString(i));
904  BOOST_CHECK(addrman.Add({CAddress(addr, NODE_NONE)}, source));
905  addrman.Good(addr);
906 
907  // No collision yet.
908  BOOST_CHECK(addrman.size() == i);
909  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
910  }
911 
912  // Collision between 36 and 19.
913  CService addr36 = ResolveService("250.1.1.36");
914  BOOST_CHECK(addrman.Add({CAddress(addr36, NODE_NONE)}, source));
915  addrman.Good(addr36);
916 
917  BOOST_CHECK(addrman.size() == 36);
918  BOOST_CHECK_EQUAL(addrman.SelectTriedCollision().ToString(), "250.1.1.19:0");
919 
920  // 36 should be discarded and 19 not evicted.
921  addrman.ResolveCollisions();
922  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
923 
924  // Lets create two collisions.
925  for (unsigned int i = 37; i < 59; i++) {
926  CService addr = ResolveService("250.1.1."+ToString(i));
927  BOOST_CHECK(addrman.Add({CAddress(addr, NODE_NONE)}, source));
928  addrman.Good(addr);
929 
930  BOOST_CHECK(addrman.size() == i);
931  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
932  }
933 
934  // Cause a collision.
935  CService addr59 = ResolveService("250.1.1.59");
936  BOOST_CHECK(addrman.Add({CAddress(addr59, NODE_NONE)}, source));
937  addrman.Good(addr59);
938  BOOST_CHECK(addrman.size() == 59);
939 
940  BOOST_CHECK_EQUAL(addrman.SelectTriedCollision().ToString(), "250.1.1.10:0");
941 
942  // Cause a second collision.
943  BOOST_CHECK(!addrman.Add({CAddress(addr36, NODE_NONE)}, source));
944  addrman.Good(addr36);
945  BOOST_CHECK(addrman.size() == 59);
946 
947  BOOST_CHECK(addrman.SelectTriedCollision().ToString() != "[::]:0");
948  addrman.ResolveCollisions();
949  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
950 }
951 
952 BOOST_AUTO_TEST_CASE(addrman_evictionworks)
953 {
954  CAddrManTest addrman;
955 
956  BOOST_CHECK(addrman.size() == 0);
957 
958  // Empty addrman should return blank addrman info.
959  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
960 
961  // Add 35 addresses
962  CNetAddr source = ResolveIP("252.2.2.2");
963  for (unsigned int i = 1; i < 36; i++) {
964  CService addr = ResolveService("250.1.1."+ToString(i));
965  BOOST_CHECK(addrman.Add({CAddress(addr, NODE_NONE)}, source));
966  addrman.Good(addr);
967 
968  // No collision yet.
969  BOOST_CHECK(addrman.size() == i);
970  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
971  }
972 
973  // Collision between 36 and 19.
974  CService addr = ResolveService("250.1.1.36");
975  BOOST_CHECK(addrman.Add({CAddress(addr, NODE_NONE)}, source));
976  addrman.Good(addr);
977 
978  BOOST_CHECK_EQUAL(addrman.size(), 36);
979  CAddrInfo info = addrman.SelectTriedCollision();
980  BOOST_CHECK_EQUAL(info.ToString(), "250.1.1.19:0");
981 
982  // Ensure test of address fails, so that it is evicted.
983  addrman.SimConnFail(info);
984 
985  // Should swap 36 for 19.
986  addrman.ResolveCollisions();
987  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
988 
989  // If 36 was swapped for 19, then this should cause no collisions.
990  BOOST_CHECK(!addrman.Add({CAddress(addr, NODE_NONE)}, source));
991  addrman.Good(addr);
992 
993  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
994 
995  // If we insert 19 it should collide with 36
996  CService addr19 = ResolveService("250.1.1.19");
997  BOOST_CHECK(!addrman.Add({CAddress(addr19, NODE_NONE)}, source));
998  addrman.Good(addr19);
999 
1000  BOOST_CHECK_EQUAL(addrman.SelectTriedCollision().ToString(), "250.1.1.36:0");
1001 
1002  addrman.ResolveCollisions();
1003  BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
1004 }
1005 
1007 {
1008  CAddrManUncorrupted addrmanUncorrupted;
1009 
1010  CService addr1, addr2, addr3;
1011  BOOST_CHECK(Lookup("250.7.1.1", addr1, 8333, false));
1012  BOOST_CHECK(Lookup("250.7.2.2", addr2, 9999, false));
1013  BOOST_CHECK(Lookup("250.7.3.3", addr3, 9999, false));
1014  BOOST_CHECK(Lookup("250.7.3.3"s, addr3, 9999, false));
1015  BOOST_CHECK(!Lookup("250.7.3.3\0example.com"s, addr3, 9999, false));
1016 
1017  // Add three addresses to new table.
1018  CService source;
1019  BOOST_CHECK(Lookup("252.5.1.1", source, 8333, false));
1020  std::vector<CAddress> addresses{CAddress(addr1, NODE_NONE), CAddress(addr2, NODE_NONE), CAddress(addr3, NODE_NONE)};
1021  BOOST_CHECK(addrmanUncorrupted.Add(addresses, source));
1022  BOOST_CHECK(addrmanUncorrupted.size() == 3);
1023 
1024  // Test that the de-serialization does not throw an exception.
1025  CDataStream ssPeers1 = AddrmanToStream(addrmanUncorrupted);
1026  bool exceptionThrown = false;
1027  CAddrMan addrman1(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 100);
1028 
1029  BOOST_CHECK(addrman1.size() == 0);
1030  try {
1031  unsigned char pchMsgTmp[4];
1032  ssPeers1 >> pchMsgTmp;
1033  ssPeers1 >> addrman1;
1034  } catch (const std::exception&) {
1035  exceptionThrown = true;
1036  }
1037 
1038  BOOST_CHECK(addrman1.size() == 3);
1039  BOOST_CHECK(exceptionThrown == false);
1040 
1041  // Test that ReadFromStream creates an addrman with the correct number of addrs.
1042  CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted);
1043 
1044  CAddrMan addrman2(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 100);
1045  BOOST_CHECK(addrman2.size() == 0);
1046  ReadFromStream(addrman2, ssPeers2);
1047  BOOST_CHECK(addrman2.size() == 3);
1048 }
1049 
1050 
1051 BOOST_AUTO_TEST_CASE(load_addrman_corrupted)
1052 {
1053  CAddrManCorrupted addrmanCorrupted;
1054 
1055  // Test that the de-serialization of corrupted addrman throws an exception.
1056  CDataStream ssPeers1 = AddrmanToStream(addrmanCorrupted);
1057  bool exceptionThrown = false;
1058  CAddrMan addrman1(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 100);
1059  BOOST_CHECK(addrman1.size() == 0);
1060  try {
1061  unsigned char pchMsgTmp[4];
1062  ssPeers1 >> pchMsgTmp;
1063  ssPeers1 >> addrman1;
1064  } catch (const std::exception&) {
1065  exceptionThrown = true;
1066  }
1067  // Even though de-serialization failed addrman is not left in a clean state.
1068  BOOST_CHECK(addrman1.size() == 1);
1069  BOOST_CHECK(exceptionThrown);
1070 
1071  // Test that ReadFromStream fails if peers.dat is corrupt
1072  CDataStream ssPeers2 = AddrmanToStream(addrmanCorrupted);
1073 
1074  CAddrMan addrman2(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 100);
1075  BOOST_CHECK(addrman2.size() == 0);
1076  BOOST_CHECK_THROW(ReadFromStream(addrman2, ssPeers2), std::ios_base::failure);
1077 }
1078 
1079 
CAddrMan::Create
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Create a new entry and add it to the internal data structures mapInfo, mapAddr and vRandom.
Definition: addrman.cpp:415
CService
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:539
CAddrInfo::GetNewBucket
int GetNewBucket(const uint256 &nKey, const CNetAddr &src, const std::vector< bool > &asmap) const
Calculate in which "new" bucket this entry belongs, given a certain source.
Definition: addrman.cpp:51
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:167
CAddrManTest::CAddrManTest
CAddrManTest(bool makeDeterministic=true, std::vector< bool > asmap=std::vector< bool >())
Definition: addrman_tests.cpp:84
ToString
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:87
SER_DISK
@ SER_DISK
Definition: serialize.h:139
CAddrManTest::deterministic
bool deterministic
Definition: addrman_tests.cpp:82
asmap.h
CAddrManTest::SimConnFail
void SimConnFail(const CService &addr)
Definition: addrman_tests.cpp:125
setup_common.h
CAddrMan::Delete
void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Delete an entry. It must not be in tried, and have refcount 0.
Definition: addrman.cpp:453
CDataStream::data
value_type * data()
Definition: streams.h:264
string.h
CAddrMan::Select
CAddrInfo Select(bool newOnly=false) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Choose an address to connect to.
Definition: addrman.h:226
CNetAddr
Network address.
Definition: netaddress.h:118
source
const char * source
Definition: rpcconsole.cpp:63
ResolveService
static CService ResolveService(const std::string &ip, uint16_t port=0)
Definition: addrman_tests.cpp:144
BOOST_AUTO_TEST_CASE
BOOST_AUTO_TEST_CASE(addrman_simple)
Definition: addrman_tests.cpp:166
CAddrMan::GetAddr
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Return all or many randomly selected addresses, optionally by network.
Definition: addrman.h:243
clientversion.h
CAddrManTest::Find
CAddrInfo * Find(const CNetAddr &addr, int *pnId=nullptr)
Definition: addrman_tests.cpp:91
chainparams.h
CAddrManCorrupted::Serialize
void Serialize(CDataStream &s) const override
Definition: addrman_tests.cpp:46
BOOST_FIXTURE_TEST_SUITE
#define BOOST_FIXTURE_TEST_SUITE(a, b)
Definition: object.cpp:14
CAddress::nTime
uint32_t nTime
Always included in serialization.
Definition: protocol.h:440
BOOST_AUTO_TEST_SUITE_END
BOOST_AUTO_TEST_SUITE_END()
cs
static void pool cs
Definition: mempool_eviction.cpp:12
ReadFromStream
void ReadFromStream(CAddrMan &addr, CDataStream &ssPeers)
Only used by tests.
Definition: addrdb.cpp:179
CAddrInfo
Extended statistics about a CAddress.
Definition: addrman.h:28
addrdb.h
random.h
CService::ToString
std::string ToString() const
Definition: netaddress.cpp:1037
ip
static CService ip(uint32_t i)
Definition: denialofservice_tests.cpp:30
CAddrManCorrupted
Definition: addrman_tests.cpp:43
CAddrManUncorrupted
Definition: addrman_tests.cpp:34
CAddrManTest
Definition: addrman_tests.cpp:79
BasicTestingSetup
Basic testing setup.
Definition: setup_common.h:76
CAddrMan::ResolveCollisions
void ResolveCollisions() EXCLUSIVE_LOCKS_REQUIRED(!cs)
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
Definition: addrman.h:203
CAddrMan::Add
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Add addresses to addrman's new table.
Definition: addrman.h:167
uint256
256-bit opaque blob.
Definition: uint256.h:124
addr1
static const std::string addr1
Definition: key_tests.cpp:24
CDataStream::size
size_type size() const
Definition: streams.h:255
CService::GetPort
uint16_t GetPort() const
Definition: netaddress.cpp:955
NODE_NONE
@ NODE_NONE
Definition: protocol.h:274
CChainParams::MessageStart
const CMessageHeader::MessageStartChars & MessageStart() const
Definition: chainparams.h:83
CAddrInfo::GetTriedBucket
int GetTriedBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "tried" bucket this entry belongs.
Definition: addrman.cpp:41
CAddrManTest::Delete
void Delete(int nId)
Definition: addrman_tests.cpp:103
strprintf
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
CAddrMan
Stochastical (IP) address manager.
Definition: addrman.h:142
GetAdjustedTime
int64_t GetAdjustedTime()
Definition: timedata.cpp:34
CAddress
A CService with information about it as peer.
Definition: protocol.h:358
CAddrManUncorrupted::Serialize
void Serialize(CDataStream &s) const override
Definition: addrman_tests.cpp:37
addr2
static const std::string addr2
Definition: key_tests.cpp:25
LOCK
#define LOCK(cs)
Definition: sync.h:226
ADDRMAN_BUCKET_SIZE
static constexpr int ADDRMAN_BUCKET_SIZE
Definition: addrman.h:137
CAddrMan::Good
void Good(const CService &addr, int64_t nTime=GetAdjustedTime()) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Mark an entry as accessible.
Definition: addrman.h:183
FromBytes
static std::vector< bool > FromBytes(const unsigned char *source, int vector_size)
Definition: addrman_tests.cpp:152
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
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:100
ADDRMAN_NEW_BUCKET_COUNT
static constexpr int ADDRMAN_NEW_BUCKET_COUNT
Definition: addrman.h:133
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:536
ResolveIP
static CNetAddr ResolveIP(const std::string &ip)
Definition: addrman_tests.cpp:137
CDataStream
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:204
addrman.h
SER_NETWORK
@ SER_NETWORK
Definition: serialize.h:138
BOOST_CHECK_THROW
#define BOOST_CHECK_THROW(stmt, excMatch)
Definition: object.cpp:19
CAddrManSerializationMock::CAddrManSerializationMock
CAddrManSerializationMock()
Definition: addrman_tests.cpp:29
CAddrMan::Find
CAddrInfo * Find(const CNetAddr &addr, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Find an entry.
Definition: addrman.cpp:400
CAddrManTest::Create
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr)
Definition: addrman_tests.cpp:97
netbase.h
CAddrManTest::GetBucketAndEntry
std::pair< int, int > GetBucketAndEntry(const CAddress &addr)
Definition: addrman_tests.cpp:110
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:195
CAddrMan::Serialize
void Serialize(Stream &s_) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:122
CDataStream::str
std::string str() const
Definition: streams.h:242
CAddrMan::size
size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Return the number of (unique) addresses in all tables.
Definition: addrman.h:159
AddrmanToStream
static CDataStream AddrmanToStream(const CAddrManSerializationMock &_addrman)
Definition: addrman_tests.cpp:69
Serialize
void Serialize(Stream &s, char a)
Definition: serialize.h:199
SER_GETHASH
@ SER_GETHASH
Definition: serialize.h:140
CAddrMan::SelectTriedCollision
CAddrInfo SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs)
Randomly select an address in tried that another address is attempting to evict.
Definition: addrman.h:213
BOOST_CHECK
#define BOOST_CHECK(expr)
Definition: object.cpp:17
BOOST_CHECK_EQUAL
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
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:1015
CAddrManSerializationMock
Definition: addrman_tests.cpp:24
uint256::ONE
static const uint256 ONE
Definition: uint256.h:130