Bitcoin ABC  0.24.10
P2P Digital Currency
addrman.cpp
Go to the documentation of this file.
1 // Copyright (c) 2012 Pieter Wuille
2 // Copyright (c) 2012-2016 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <addrman.h>
7 
8 #include <hash.h>
9 #include <logging.h>
10 #include <serialize.h>
11 #include <util/check.h>
12 
13 #include <cmath>
14 
16  const std::vector<bool> &asmap) const {
17  uint64_t hash1 =
18  (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetCheapHash();
19  uint64_t hash2 = (CHashWriter(SER_GETHASH, 0)
20  << nKey << GetGroup(asmap)
22  .GetCheapHash();
23  int tried_bucket = hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
24  uint32_t mapped_as = GetMappedAS(asmap);
25  LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to tried bucket %i\n",
26  ToStringIP(), mapped_as, tried_bucket);
27  return tried_bucket;
28 }
29 
30 int CAddrInfo::GetNewBucket(const uint256 &nKey, const CNetAddr &src,
31  const std::vector<bool> &asmap) const {
32  std::vector<uint8_t> vchSourceGroupKey = src.GetGroup(asmap);
33  uint64_t hash1 = (CHashWriter(SER_GETHASH, 0)
34  << nKey << GetGroup(asmap) << vchSourceGroupKey)
35  .GetCheapHash();
36  uint64_t hash2 = (CHashWriter(SER_GETHASH, 0)
37  << nKey << vchSourceGroupKey
39  .GetCheapHash();
40  int new_bucket = hash2 % ADDRMAN_NEW_BUCKET_COUNT;
41  uint32_t mapped_as = GetMappedAS(asmap);
42  LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to new bucket %i\n",
43  ToStringIP(), mapped_as, new_bucket);
44  return new_bucket;
45 }
46 
47 int CAddrInfo::GetBucketPosition(const uint256 &nKey, bool fNew,
48  int nBucket) const {
49  uint64_t hash1 = (CHashWriter(SER_GETHASH, 0)
50  << nKey << (fNew ? 'N' : 'K') << nBucket << GetKey())
51  .GetCheapHash();
52  return hash1 % ADDRMAN_BUCKET_SIZE;
53 }
54 
55 bool CAddrInfo::IsTerrible(int64_t nNow) const {
56  // never remove things tried in the last minute
57  if (nLastTry && nLastTry >= nNow - 60) {
58  return false;
59  }
60 
61  // came in a flying DeLorean
62  if (nTime > nNow + 10 * 60) {
63  return true;
64  }
65 
66  // not seen in recent history
67  if (nTime == 0 || nNow - nTime > ADDRMAN_HORIZON_DAYS * 24 * 60 * 60) {
68  return true;
69  }
70 
71  // tried N times and never a success
72  if (nLastSuccess == 0 && nAttempts >= ADDRMAN_RETRIES) {
73  return true;
74  }
75 
76  if (nNow - nLastSuccess > ADDRMAN_MIN_FAIL_DAYS * 24 * 60 * 60 &&
78  // N successive failures in the last week
79  return true;
80  }
81 
82  return false;
83 }
84 
85 double CAddrInfo::GetChance(int64_t nNow) const {
86  double fChance = 1.0;
87  int64_t nSinceLastTry = std::max<int64_t>(nNow - nLastTry, 0);
88 
89  // deprioritize very recent attempts away
90  if (nSinceLastTry < 60 * 10) {
91  fChance *= 0.01;
92  }
93 
94  // deprioritize 66% after each failed attempt, but at most 1/28th to avoid
95  // the search taking forever or overly penalizing outages.
96  fChance *= std::pow(0.66, std::min(nAttempts, 8));
97 
98  return fChance;
99 }
100 
101 CAddrInfo *CAddrMan::Find(const CNetAddr &addr, int *pnId) {
102  std::map<CNetAddr, int>::iterator it = mapAddr.find(addr);
103  if (it == mapAddr.end()) {
104  return nullptr;
105  }
106  if (pnId) {
107  *pnId = (*it).second;
108  }
109  std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
110  if (it2 != mapInfo.end()) {
111  return &(*it2).second;
112  }
113  return nullptr;
114 }
115 
116 CAddrInfo *CAddrMan::Create(const CAddress &addr, const CNetAddr &addrSource,
117  int *pnId) {
118  int nId = nIdCount++;
119  mapInfo[nId] = CAddrInfo(addr, addrSource);
120  mapAddr[addr] = nId;
121  mapInfo[nId].nRandomPos = vRandom.size();
122  vRandom.push_back(nId);
123  if (pnId) {
124  *pnId = nId;
125  }
126  return &mapInfo[nId];
127 }
128 
129 void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2) {
130  if (nRndPos1 == nRndPos2) {
131  return;
132  }
133 
134  assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
135 
136  int nId1 = vRandom[nRndPos1];
137  int nId2 = vRandom[nRndPos2];
138 
139  assert(mapInfo.count(nId1) == 1);
140  assert(mapInfo.count(nId2) == 1);
141 
142  mapInfo[nId1].nRandomPos = nRndPos2;
143  mapInfo[nId2].nRandomPos = nRndPos1;
144 
145  vRandom[nRndPos1] = nId2;
146  vRandom[nRndPos2] = nId1;
147 }
148 
149 void CAddrMan::Delete(int nId) {
150  assert(mapInfo.count(nId) != 0);
151  CAddrInfo &info = mapInfo[nId];
152  assert(!info.fInTried);
153  assert(info.nRefCount == 0);
154 
155  SwapRandom(info.nRandomPos, vRandom.size() - 1);
156  vRandom.pop_back();
157  mapAddr.erase(info);
158  mapInfo.erase(nId);
159  nNew--;
160 }
161 
162 void CAddrMan::ClearNew(int nUBucket, int nUBucketPos) {
163  // if there is an entry in the specified bucket, delete it.
164  if (vvNew[nUBucket][nUBucketPos] != -1) {
165  int nIdDelete = vvNew[nUBucket][nUBucketPos];
166  CAddrInfo &infoDelete = mapInfo[nIdDelete];
167  assert(infoDelete.nRefCount > 0);
168  infoDelete.nRefCount--;
169  vvNew[nUBucket][nUBucketPos] = -1;
170  if (infoDelete.nRefCount == 0) {
171  Delete(nIdDelete);
172  }
173  }
174 }
175 
176 void CAddrMan::MakeTried(CAddrInfo &info, int nId) {
177  // remove the entry from all new buckets
178  const int start_bucket{info.GetNewBucket(nKey, m_asmap)};
179  for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; ++n) {
180  const int bucket{(start_bucket + n) % ADDRMAN_NEW_BUCKET_COUNT};
181  const int pos{info.GetBucketPosition(nKey, true, bucket)};
182  if (vvNew[bucket][pos] == nId) {
183  vvNew[bucket][pos] = -1;
184  info.nRefCount--;
185  if (info.nRefCount == 0) {
186  break;
187  }
188  }
189  }
190  nNew--;
191 
192  assert(info.nRefCount == 0);
193 
194  // which tried bucket to move the entry to
195  int nKBucket = info.GetTriedBucket(nKey, m_asmap);
196  int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
197 
198  // first make space to add it (the existing tried entry there is moved to
199  // new, deleting whatever is there).
200  if (vvTried[nKBucket][nKBucketPos] != -1) {
201  // find an item to evict
202  int nIdEvict = vvTried[nKBucket][nKBucketPos];
203  assert(mapInfo.count(nIdEvict) == 1);
204  CAddrInfo &infoOld = mapInfo[nIdEvict];
205 
206  // Remove the to-be-evicted item from the tried set.
207  infoOld.fInTried = false;
208  vvTried[nKBucket][nKBucketPos] = -1;
209  nTried--;
210 
211  // find which new bucket it belongs to
212  int nUBucket = infoOld.GetNewBucket(nKey, m_asmap);
213  int nUBucketPos = infoOld.GetBucketPosition(nKey, true, nUBucket);
214  ClearNew(nUBucket, nUBucketPos);
215  assert(vvNew[nUBucket][nUBucketPos] == -1);
216 
217  // Enter it into the new set again.
218  infoOld.nRefCount = 1;
219  vvNew[nUBucket][nUBucketPos] = nIdEvict;
220  nNew++;
221  }
222  assert(vvTried[nKBucket][nKBucketPos] == -1);
223 
224  vvTried[nKBucket][nKBucketPos] = nId;
225  nTried++;
226  info.fInTried = true;
227 }
228 
229 void CAddrMan::Good_(const CService &addr, bool test_before_evict,
230  int64_t nTime) {
231  int nId;
232 
233  nLastGood = nTime;
234 
235  CAddrInfo *pinfo = Find(addr, &nId);
236 
237  // if not found, bail out
238  if (!pinfo) {
239  return;
240  }
241 
242  CAddrInfo &info = *pinfo;
243 
244  // check whether we are talking about the exact same CService (including
245  // same port)
246  if (info != addr) {
247  return;
248  }
249 
250  // update info
251  info.nLastSuccess = nTime;
252  info.nLastTry = nTime;
253  info.nAttempts = 0;
254  // nTime is not updated here, to avoid leaking information about
255  // currently-connected peers.
256 
257  // if it is already in the tried set, don't do anything else
258  if (info.fInTried) {
259  return;
260  }
261 
262  // if it is not in new, something bad happened
263  if (!Assume(info.nRefCount > 0)) {
264  return;
265  }
266 
267  // which tried bucket to move the entry to
268  int tried_bucket = info.GetTriedBucket(nKey, m_asmap);
269  int tried_bucket_pos = info.GetBucketPosition(nKey, false, tried_bucket);
270 
271  // Will moving this address into tried evict another entry?
272  if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) {
273  // Output the entry we'd be colliding with, for debugging purposes
274  auto colliding_entry =
275  mapInfo.find(vvTried[tried_bucket][tried_bucket_pos]);
277  "Collision inserting element into tried table (%s), moving %s "
278  "to m_tried_collisions=%d\n",
279  colliding_entry != mapInfo.end()
280  ? colliding_entry->second.ToString()
281  : "",
282  addr.ToString(), m_tried_collisions.size());
284  m_tried_collisions.insert(nId);
285  }
286  } else {
287  LogPrint(BCLog::ADDRMAN, "Moving %s to tried\n", addr.ToString());
288 
289  // move nId to the tried tables
290  MakeTried(info, nId);
291  }
292 }
293 
294 bool CAddrMan::Add_(const CAddress &addr, const CNetAddr &source,
295  int64_t nTimePenalty) {
296  if (!addr.IsRoutable()) {
297  return false;
298  }
299 
300  bool fNew = false;
301  int nId;
302  CAddrInfo *pinfo = Find(addr, &nId);
303 
304  // Do not set a penalty for a source's self-announcement
305  if (addr == source) {
306  nTimePenalty = 0;
307  }
308 
309  if (pinfo) {
310  // periodically update nTime
311  bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
312  int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
313  if (addr.nTime &&
314  (!pinfo->nTime ||
315  pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty)) {
316  pinfo->nTime = std::max((int64_t)0, addr.nTime - nTimePenalty);
317  }
318 
319  // add services
320  pinfo->nServices = ServiceFlags(pinfo->nServices | addr.nServices);
321 
322  // do not update if no new information is present
323  if (!addr.nTime || (pinfo->nTime && addr.nTime <= pinfo->nTime)) {
324  return false;
325  }
326 
327  // do not update if the entry was already in the "tried" table
328  if (pinfo->fInTried) {
329  return false;
330  }
331 
332  // do not update if the max reference count is reached
334  return false;
335  }
336 
337  // stochastic test: previous nRefCount == N: 2^N times harder to
338  // increase it
339  int nFactor = 1;
340  for (int n = 0; n < pinfo->nRefCount; n++) {
341  nFactor *= 2;
342  }
343 
344  if (nFactor > 1 && (insecure_rand.randrange(nFactor) != 0)) {
345  return false;
346  }
347  } else {
348  pinfo = Create(addr, source, &nId);
349  pinfo->nTime =
350  std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
351  nNew++;
352  fNew = true;
353  }
354 
355  int nUBucket = pinfo->GetNewBucket(nKey, source, m_asmap);
356  int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket);
357  if (vvNew[nUBucket][nUBucketPos] != nId) {
358  bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
359  if (!fInsert) {
360  CAddrInfo &infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
361  if (infoExisting.IsTerrible() ||
362  (infoExisting.nRefCount > 1 && pinfo->nRefCount == 0)) {
363  // Overwrite the existing new table entry.
364  fInsert = true;
365  }
366  }
367  if (fInsert) {
368  ClearNew(nUBucket, nUBucketPos);
369  pinfo->nRefCount++;
370  vvNew[nUBucket][nUBucketPos] = nId;
371  } else if (pinfo->nRefCount == 0) {
372  Delete(nId);
373  }
374  }
375  return fNew;
376 }
377 
378 void CAddrMan::Attempt_(const CService &addr, bool fCountFailure,
379  int64_t nTime) {
380  CAddrInfo *pinfo = Find(addr);
381 
382  // if not found, bail out
383  if (!pinfo) {
384  return;
385  }
386 
387  CAddrInfo &info = *pinfo;
388 
389  // check whether we are talking about the exact same CService (including
390  // same port)
391  if (info != addr) {
392  return;
393  }
394 
395  // update info
396  info.nLastTry = nTime;
397  if (fCountFailure && info.nLastCountAttempt < nLastGood) {
398  info.nLastCountAttempt = nTime;
399  info.nAttempts++;
400  }
401 }
402 
404  if (size() == 0) {
405  return CAddrInfo();
406  }
407 
408  if (newOnly && nNew == 0) {
409  return CAddrInfo();
410  }
411 
412  // Use a 50% chance for choosing between tried and new table entries.
413  if (!newOnly &&
414  (nTried > 0 && (nNew == 0 || insecure_rand.randbool() == 0))) {
415  // use a tried node
416  double fChanceFactor = 1.0;
417  while (1) {
419  int nKBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE);
420  while (vvTried[nKBucket][nKBucketPos] == -1) {
421  nKBucket = (nKBucket + insecure_rand.randbits(
424  nKBucketPos = (nKBucketPos + insecure_rand.randbits(
427  }
428  int nId = vvTried[nKBucket][nKBucketPos];
429  assert(mapInfo.count(nId) == 1);
430  CAddrInfo &info = mapInfo[nId];
431  if (insecure_rand.randbits(30) <
432  fChanceFactor * info.GetChance() * (1 << 30)) {
433  return info;
434  }
435  fChanceFactor *= 1.2;
436  }
437  } else {
438  // use a new node
439  double fChanceFactor = 1.0;
440  while (1) {
442  int nUBucketPos = insecure_rand.randrange(ADDRMAN_BUCKET_SIZE);
443  while (vvNew[nUBucket][nUBucketPos] == -1) {
444  nUBucket = (nUBucket + insecure_rand.randbits(
447  nUBucketPos = (nUBucketPos + insecure_rand.randbits(
450  }
451  int nId = vvNew[nUBucket][nUBucketPos];
452  assert(mapInfo.count(nId) == 1);
453  CAddrInfo &info = mapInfo[nId];
454  if (insecure_rand.randbits(30) <
455  fChanceFactor * info.GetChance() * (1 << 30)) {
456  return info;
457  }
458  fChanceFactor *= 1.2;
459  }
460  }
461 }
462 
463 #ifdef DEBUG_ADDRMAN
464 int CAddrMan::Check_() {
465  std::set<int> setTried;
466  std::map<int, int> mapNew;
467 
468  if (vRandom.size() != size_t(nTried + nNew)) {
469  return -7;
470  }
471 
472  for (const auto &entry : mapInfo) {
473  int n = entry.first;
474  const CAddrInfo &info = entry.second;
475  if (info.fInTried) {
476  if (!info.nLastSuccess) {
477  return -1;
478  }
479  if (info.nRefCount) {
480  return -2;
481  }
482  setTried.insert(n);
483  } else {
484  if (info.nRefCount < 0 ||
486  return -3;
487  }
488  if (!info.nRefCount) {
489  return -4;
490  }
491  mapNew[n] = info.nRefCount;
492  }
493  if (mapAddr[info] != n) {
494  return -5;
495  }
496  if (info.nRandomPos < 0 || size_t(info.nRandomPos) >= vRandom.size() ||
497  vRandom[info.nRandomPos] != n) {
498  return -14;
499  }
500  if (info.nLastTry < 0) {
501  return -6;
502  }
503  if (info.nLastSuccess < 0) {
504  return -8;
505  }
506  }
507 
508  if (setTried.size() != size_t(nTried)) {
509  return -9;
510  }
511  if (mapNew.size() != size_t(nNew)) {
512  return -10;
513  }
514 
515  for (int n = 0; n < ADDRMAN_TRIED_BUCKET_COUNT; n++) {
516  for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
517  if (vvTried[n][i] != -1) {
518  if (!setTried.count(vvTried[n][i])) {
519  return -11;
520  }
521  if (mapInfo[vvTried[n][i]].GetTriedBucket(nKey, m_asmap) != n) {
522  return -17;
523  }
524  if (mapInfo[vvTried[n][i]].GetBucketPosition(nKey, false, n) !=
525  i) {
526  return -18;
527  }
528  setTried.erase(vvTried[n][i]);
529  }
530  }
531  }
532 
533  for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
534  for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
535  if (vvNew[n][i] != -1) {
536  if (!mapNew.count(vvNew[n][i])) {
537  return -12;
538  }
539  if (mapInfo[vvNew[n][i]].GetBucketPosition(nKey, true, n) !=
540  i) {
541  return -19;
542  }
543  if (--mapNew[vvNew[n][i]] == 0) {
544  mapNew.erase(vvNew[n][i]);
545  }
546  }
547  }
548  }
549 
550  if (setTried.size()) {
551  return -13;
552  }
553  if (mapNew.size()) {
554  return -15;
555  }
556  if (nKey.IsNull()) {
557  return -16;
558  }
559 
560  return 0;
561 }
562 #endif
563 
564 void CAddrMan::GetAddr_(std::vector<CAddress> &vAddr, size_t max_addresses,
565  size_t max_pct) {
566  size_t nNodes = vRandom.size();
567  if (max_pct != 0) {
568  nNodes = max_pct * nNodes / 100;
569  }
570  if (max_addresses != 0) {
571  nNodes = std::min(nNodes, max_addresses);
572  }
573 
574  // gather a list of random nodes, skipping those of low quality
575  for (unsigned int n = 0; n < vRandom.size(); n++) {
576  if (vAddr.size() >= nNodes) {
577  break;
578  }
579 
580  int nRndPos = insecure_rand.randrange(vRandom.size() - n) + n;
581  SwapRandom(n, nRndPos);
582  assert(mapInfo.count(vRandom[n]) == 1);
583 
584  const CAddrInfo &ai = mapInfo[vRandom[n]];
585  if (!ai.IsTerrible()) {
586  vAddr.push_back(ai);
587  }
588  }
589 }
590 
591 void CAddrMan::Connected_(const CService &addr, int64_t nTime) {
592  CAddrInfo *pinfo = Find(addr);
593 
594  // if not found, bail out
595  if (!pinfo) {
596  return;
597  }
598 
599  CAddrInfo &info = *pinfo;
600 
601  // check whether we are talking about the exact same CService (including
602  // same port)
603  if (info != addr) {
604  return;
605  }
606 
607  // update info
608  int64_t nUpdateInterval = 20 * 60;
609  if (nTime - info.nTime > nUpdateInterval) {
610  info.nTime = nTime;
611  }
612 }
613 
614 void CAddrMan::SetServices_(const CService &addr, ServiceFlags nServices) {
615  CAddrInfo *pinfo = Find(addr);
616 
617  // if not found, bail out
618  if (!pinfo) {
619  return;
620  }
621 
622  CAddrInfo &info = *pinfo;
623 
624  // check whether we are talking about the exact same CService (including
625  // same port)
626  if (info != addr) {
627  return;
628  }
629 
630  // update info
631  info.nServices = nServices;
632 }
633 
635  const int64_t adjustedTime = GetAdjustedTime();
636 
637  for (std::set<int>::iterator it = m_tried_collisions.begin();
638  it != m_tried_collisions.end();) {
639  int id_new = *it;
640 
641  bool erase_collision = false;
642 
643  // If id_new not found in mapInfo remove it from m_tried_collisions.
644  auto id_new_it = mapInfo.find(id_new);
645  if (id_new_it == mapInfo.end()) {
646  erase_collision = true;
647  } else {
648  CAddrInfo &info_new = id_new_it->second;
649 
650  // Which tried bucket to move the entry to.
651  int tried_bucket = info_new.GetTriedBucket(nKey, m_asmap);
652  int tried_bucket_pos =
653  info_new.GetBucketPosition(nKey, false, tried_bucket);
654  if (!info_new.IsValid()) {
655  // id_new may no longer map to a valid address
656  erase_collision = true;
657  } else if (vvTried[tried_bucket][tried_bucket_pos] != -1) {
658  // The position in the tried bucket is not empty
659 
660  // Get the to-be-evicted address that is being tested
661  int id_old = vvTried[tried_bucket][tried_bucket_pos];
662  CAddrInfo &info_old = mapInfo[id_old];
663 
664  // Has successfully connected in last X hours
665  if (adjustedTime - info_old.nLastSuccess <
667  erase_collision = true;
668  } else if (adjustedTime - info_old.nLastTry <
670  // attempted to connect and failed in last X hours
671 
672  // Give address at least 60 seconds to successfully connect
673  if (GetAdjustedTime() - info_old.nLastTry > 60) {
675  "Replacing %s with %s in tried table\n",
676  info_old.ToString(), info_new.ToString());
677 
678  // Replaces an existing address already in the tried
679  // table with the new address
680  Good_(info_new, false, GetAdjustedTime());
681  erase_collision = true;
682  }
683  } else if (GetAdjustedTime() - info_new.nLastSuccess >
685  // If the collision hasn't resolved in some reasonable
686  // amount of time, just evict the old entry -- we must not
687  // be able to connect to it for some reason.
689  "Unable to test; replacing %s with %s in tried "
690  "table anyway\n",
691  info_old.ToString(), info_new.ToString());
692  Good_(info_new, false, GetAdjustedTime());
693  erase_collision = true;
694  }
695  } else {
696  // Collision is not actually a collision anymore
697  Good_(info_new, false, adjustedTime);
698  erase_collision = true;
699  }
700  }
701 
702  if (erase_collision) {
703  m_tried_collisions.erase(it++);
704  } else {
705  it++;
706  }
707  }
708 }
709 
711  if (m_tried_collisions.size() == 0) {
712  return CAddrInfo();
713  }
714 
715  std::set<int>::iterator it = m_tried_collisions.begin();
716 
717  // Selects a random element from m_tried_collisions
718  std::advance(it, insecure_rand.randrange(m_tried_collisions.size()));
719  int id_new = *it;
720 
721  // If id_new not found in mapInfo remove it from m_tried_collisions.
722  auto id_new_it = mapInfo.find(id_new);
723  if (id_new_it == mapInfo.end()) {
724  m_tried_collisions.erase(it);
725  return CAddrInfo();
726  }
727 
728  CAddrInfo &newInfo = id_new_it->second;
729 
730  // which tried bucket to move the entry to
731  int tried_bucket = newInfo.GetTriedBucket(nKey, m_asmap);
732  int tried_bucket_pos = newInfo.GetBucketPosition(nKey, false, tried_bucket);
733 
734  int id_old = vvTried[tried_bucket][tried_bucket_pos];
735 
736  return mapInfo[id_old];
737 }
CAddrMan::Create
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
find an entry, creating it if necessary.
Definition: addrman.cpp:116
CService
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:514
CAddrMan::nKey
uint256 nKey
secret key to randomize bucket select with
Definition: addrman.h:258
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:30
CAddrMan::Good_
void Good_(const CService &addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry "good", possibly moving it from "new" to "tried".
Definition: addrman.cpp:229
ADDRMAN_MIN_FAIL_DAYS
#define ADDRMAN_MIN_FAIL_DAYS
... in at least this many days
Definition: addrman.h:169
check.h
ADDRMAN_MAX_FAILURES
#define ADDRMAN_MAX_FAILURES
how many successive failures are allowed ...
Definition: addrman.h:166
ADDRMAN_TEST_WINDOW
static const int64_t ADDRMAN_TEST_WINDOW
the maximum time we'll spend trying to resolve a tried table collision, in seconds (40 minutes)
Definition: addrman.h:185
ADDRMAN_TRIED_BUCKET_COUNT_LOG2
#define ADDRMAN_TRIED_BUCKET_COUNT_LOG2
Stochastic address manager.
Definition: addrman.h:139
CAddrMan::Add_
bool Add_(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs)
Add an entry to the "new" table.
Definition: addrman.cpp:294
ADDRMAN_TRIED_BUCKETS_PER_GROUP
#define ADDRMAN_TRIED_BUCKETS_PER_GROUP
over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread
Definition: addrman.h:149
CAddrMan::m_tried_collisions
std::set< int > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries.
Definition: addrman.h:254
CAddrMan::SwapRandom
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) EXCLUSIVE_LOCKS_REQUIRED(cs)
Swap two elements in vRandom.
Definition: addrman.cpp:129
ADDRMAN_NEW_BUCKETS_PER_ADDRESS
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS
in how many buckets for entries with new addresses a single address may occur
Definition: addrman.h:157
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:149
ADDRMAN_SET_TRIED_COLLISION_SIZE
#define ADDRMAN_SET_TRIED_COLLISION_SIZE
the maximum number of tried addr collisions to store
Definition: addrman.h:181
FastRandomContext::randbool
bool randbool() noexcept
Generate a random boolean.
Definition: random.h:229
CNetAddr
Network address.
Definition: netaddress.h:117
source
const char * source
Definition: rpcconsole.cpp:53
CAddrInfo::nLastSuccess
int64_t nLastSuccess
last successful connection by us
Definition: addrman.h:45
CAddrInfo::GetChance
double GetChance(int64_t nNow=GetAdjustedTime()) const
Calculate the relative chance this entry should be given when selecting nodes to connect to.
Definition: addrman.cpp:85
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.cpp:634
ServiceFlags
ServiceFlags
nServices flags.
Definition: protocol.h:314
CAddrInfo::IsTerrible
bool IsTerrible(int64_t nNow=GetAdjustedTime()) const
Determine whether the statistics about this entry are bad enough so that it can just be deleted.
Definition: addrman.cpp:55
CAddress::nServices
ServiceFlags nServices
Definition: protocol.h:464
CAddrMan::Attempt_
void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry as attempted to connect.
Definition: addrman.cpp:378
ADDRMAN_REPLACEMENT_SECONDS
#define ADDRMAN_REPLACEMENT_SECONDS
how recent a successful connection should be before we allow an address to be evicted from tried
Definition: addrman.h:173
CAddress::nTime
uint32_t nTime
Definition: protocol.h:462
ADDRMAN_NEW_BUCKET_COUNT_LOG2
#define ADDRMAN_NEW_BUCKET_COUNT_LOG2
total number of buckets for new addresses
Definition: addrman.h:142
ADDRMAN_RETRIES
#define ADDRMAN_RETRIES
after how many failed attempts we give up on a new node
Definition: addrman.h:163
CNetAddr::GetGroup
std::vector< uint8_t > GetGroup(const std::vector< bool > &asmap) const
Get the canonical identifier of our network group.
Definition: netaddress.cpp:735
CAddrMan::SetServices_
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update an entry's service bits.
Definition: addrman.cpp:614
FastRandomContext::randbits
uint64_t randbits(int bits) noexcept
Generate a random (bits)-bit integer.
Definition: random.h:184
CNetAddr::ToStringIP
std::string ToStringIP() const
Definition: netaddress.cpp:540
CAddrInfo
Extended statistics about a CAddress.
Definition: addrman.h:32
Assume
#define Assume(val)
Assume is the identity function.
Definition: check.h:76
CAddrInfo::nLastCountAttempt
int64_t nLastCountAttempt
last counted attempt (memory only)
Definition: addrman.h:38
CService::ToString
std::string ToString() const
Definition: netaddress.cpp:1023
CAddrMan::SelectTriedCollision_
CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs)
Return a random to-be-evicted tried table address.
Definition: addrman.cpp:710
ADDRMAN_BUCKET_SIZE
#define ADDRMAN_BUCKET_SIZE
Definition: addrman.h:178
CService::GetKey
std::vector< uint8_t > GetKey() const
Definition: netaddress.cpp:1002
ADDRMAN_TRIED_BUCKET_COUNT
#define ADDRMAN_TRIED_BUCKET_COUNT
Convenience.
Definition: addrman.h:176
CNetAddr::IsRoutable
bool IsRoutable() const
Definition: netaddress.cpp:476
CAddrMan::ClearNew
void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs)
Clear a position in a "new" table.
Definition: addrman.cpp:162
CAddrInfo::nRefCount
int nRefCount
reference count in new sets (memory only)
Definition: addrman.h:51
CNetAddr::GetMappedAS
uint32_t GetMappedAS(const std::vector< bool > &asmap) const
Definition: netaddress.cpp:691
CAddrMan::insecure_rand
FastRandomContext insecure_rand
Source of random numbers for randomization in inner loops.
Definition: addrman.h:261
CNetAddr::IsValid
bool IsValid() const
Definition: netaddress.cpp:441
CAddrInfo::nRandomPos
int nRandomPos
position in vRandom
Definition: addrman.h:57
CAddrInfo::nLastTry
int64_t nLastTry
last try whatsoever by us (memory only)
Definition: addrman.h:35
CAddrInfo::GetBucketPosition
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
Definition: addrman.cpp:47
uint256
256-bit opaque blob.
Definition: uint256.h:127
LogPrint
#define LogPrint(category,...)
Definition: logging.h:193
ADDRMAN_NEW_BUCKET_COUNT
#define ADDRMAN_NEW_BUCKET_COUNT
Definition: addrman.h:177
ADDRMAN_BUCKET_SIZE_LOG2
#define ADDRMAN_BUCKET_SIZE_LOG2
maximum allowed number of entries in buckets for new and tried addresses
Definition: addrman.h:145
CAddrMan::MakeTried
void MakeTried(CAddrInfo &info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Move an entry from the "new" table(s) to the "tried" table.
Definition: addrman.cpp:176
CAddrInfo::GetTriedBucket
int GetTriedBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "tried" bucket this entry belongs.
Definition: addrman.cpp:15
CAddrMan::Connected_
void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs)
We have successfully connected to this peer.
Definition: addrman.cpp:591
CAddrMan::Select_
CAddrInfo Select_(bool newOnly) EXCLUSIVE_LOCKS_REQUIRED(cs)
Select an address to connect to, if newOnly is set to true, only the new table is selected from.
Definition: addrman.cpp:403
SER_GETHASH
@ SER_GETHASH
Definition: serialize.h:167
CAddrMan::m_asmap
std::vector< bool > m_asmap
Definition: addrman.h:353
GetAdjustedTime
int64_t GetAdjustedTime()
Definition: timedata.cpp:34
base_blob::IsNull
bool IsNull() const
Definition: uint256.h:30
CAddress
A CService with information about it as peer.
Definition: protocol.h:421
CAddrInfo::nAttempts
int nAttempts
connection attempts since last successful attempt
Definition: addrman.h:48
CHashWriter
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:99
logging.h
FastRandomContext::randrange
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
Definition: random.h:204
hash.h
serialize.h
addrman.h
BCLog::ADDRMAN
@ ADDRMAN
Definition: logging.h:47
CAddrMan::Find
CAddrInfo * Find(const CNetAddr &addr, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Find an entry.
Definition: addrman.cpp:101
CAddrInfo::fInTried
bool fInTried
in tried set? (memory only)
Definition: addrman.h:54
CAddrMan::size
size_t size() const
Return the number of (unique) addresses in all tables.
Definition: addrman.h:646
ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP
#define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP
over how many buckets entries with new addresses originating from a single group are spread
Definition: addrman.h:153
ADDRMAN_HORIZON_DAYS
#define ADDRMAN_HORIZON_DAYS
how old addresses can maximally be
Definition: addrman.h:160
BCLog::NET
@ NET
Definition: logging.h:38
CAddrMan::GetAddr_
void GetAddr_(std::vector< CAddress > &vAddr, size_t max_addresses, size_t max_pct) EXCLUSIVE_LOCKS_REQUIRED(cs)
Select several addresses at once.
Definition: addrman.cpp:564