BSHA3  0.17.99
P2P Blockchain, based on Bitcoin
addrman.cpp
Go to the documentation of this file.
1 // Copyright (c) 2012 Pieter Wuille
2 // Copyright (c) 2012-2018 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 <serialize.h>
10 #include <streams.h>
11 
12 int CAddrInfo::GetTriedBucket(const uint256& nKey) const
13 {
14  uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetKey()).GetHash().GetCheapHash();
15  uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << (hash1 % ADDRMAN_TRIED_BUCKETS_PER_GROUP)).GetHash().GetCheapHash();
16  return hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
17 }
18 
19 int CAddrInfo::GetNewBucket(const uint256& nKey, const CNetAddr& src) const
20 {
21  std::vector<unsigned char> vchSourceGroupKey = src.GetGroup();
22  uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << GetGroup() << vchSourceGroupKey).GetHash().GetCheapHash();
23  uint64_t hash2 = (CHashWriter(SER_GETHASH, 0) << nKey << vchSourceGroupKey << (hash1 % ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP)).GetHash().GetCheapHash();
24  return hash2 % ADDRMAN_NEW_BUCKET_COUNT;
25 }
26 
27 int CAddrInfo::GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
28 {
29  uint64_t hash1 = (CHashWriter(SER_GETHASH, 0) << nKey << (fNew ? 'N' : 'K') << nBucket << GetKey()).GetHash().GetCheapHash();
30  return hash1 % ADDRMAN_BUCKET_SIZE;
31 }
32 
33 bool CAddrInfo::IsTerrible(int64_t nNow) const
34 {
35  if (nLastTry && nLastTry >= nNow - 60) // never remove things tried in the last minute
36  return false;
37 
38  if (nTime > nNow + 10 * 60) // came in a flying DeLorean
39  return true;
40 
41  if (nTime == 0 || nNow - nTime > ADDRMAN_HORIZON_DAYS * 24 * 60 * 60) // not seen in recent history
42  return true;
43 
44  if (nLastSuccess == 0 && nAttempts >= ADDRMAN_RETRIES) // tried N times and never a success
45  return true;
46 
47  if (nNow - nLastSuccess > ADDRMAN_MIN_FAIL_DAYS * 24 * 60 * 60 && nAttempts >= ADDRMAN_MAX_FAILURES) // N successive failures in the last week
48  return true;
49 
50  return false;
51 }
52 
53 double CAddrInfo::GetChance(int64_t nNow) const
54 {
55  double fChance = 1.0;
56  int64_t nSinceLastTry = std::max<int64_t>(nNow - nLastTry, 0);
57 
58  // deprioritize very recent attempts away
59  if (nSinceLastTry < 60 * 10)
60  fChance *= 0.01;
61 
62  // deprioritize 66% after each failed attempt, but at most 1/28th to avoid the search taking forever or overly penalizing outages.
63  fChance *= pow(0.66, std::min(nAttempts, 8));
64 
65  return fChance;
66 }
67 
68 CAddrInfo* CAddrMan::Find(const CNetAddr& addr, int* pnId)
69 {
70  std::map<CNetAddr, int>::iterator it = mapAddr.find(addr);
71  if (it == mapAddr.end())
72  return nullptr;
73  if (pnId)
74  *pnId = (*it).second;
75  std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
76  if (it2 != mapInfo.end())
77  return &(*it2).second;
78  return nullptr;
79 }
80 
81 CAddrInfo* CAddrMan::Create(const CAddress& addr, const CNetAddr& addrSource, int* pnId)
82 {
83  int nId = nIdCount++;
84  mapInfo[nId] = CAddrInfo(addr, addrSource);
85  mapAddr[addr] = nId;
86  mapInfo[nId].nRandomPos = vRandom.size();
87  vRandom.push_back(nId);
88  if (pnId)
89  *pnId = nId;
90  return &mapInfo[nId];
91 }
92 
93 void CAddrMan::SwapRandom(unsigned int nRndPos1, unsigned int nRndPos2)
94 {
95  if (nRndPos1 == nRndPos2)
96  return;
97 
98  assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
99 
100  int nId1 = vRandom[nRndPos1];
101  int nId2 = vRandom[nRndPos2];
102 
103  assert(mapInfo.count(nId1) == 1);
104  assert(mapInfo.count(nId2) == 1);
105 
106  mapInfo[nId1].nRandomPos = nRndPos2;
107  mapInfo[nId2].nRandomPos = nRndPos1;
108 
109  vRandom[nRndPos1] = nId2;
110  vRandom[nRndPos2] = nId1;
111 }
112 
113 void CAddrMan::Delete(int nId)
114 {
115  assert(mapInfo.count(nId) != 0);
116  CAddrInfo& info = mapInfo[nId];
117  assert(!info.fInTried);
118  assert(info.nRefCount == 0);
119 
120  SwapRandom(info.nRandomPos, vRandom.size() - 1);
121  vRandom.pop_back();
122  mapAddr.erase(info);
123  mapInfo.erase(nId);
124  nNew--;
125 }
126 
127 void CAddrMan::ClearNew(int nUBucket, int nUBucketPos)
128 {
129  // if there is an entry in the specified bucket, delete it.
130  if (vvNew[nUBucket][nUBucketPos] != -1) {
131  int nIdDelete = vvNew[nUBucket][nUBucketPos];
132  CAddrInfo& infoDelete = mapInfo[nIdDelete];
133  assert(infoDelete.nRefCount > 0);
134  infoDelete.nRefCount--;
135  vvNew[nUBucket][nUBucketPos] = -1;
136  if (infoDelete.nRefCount == 0) {
137  Delete(nIdDelete);
138  }
139  }
140 }
141 
142 void CAddrMan::MakeTried(CAddrInfo& info, int nId)
143 {
144  // remove the entry from all new buckets
145  for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
146  int pos = info.GetBucketPosition(nKey, true, bucket);
147  if (vvNew[bucket][pos] == nId) {
148  vvNew[bucket][pos] = -1;
149  info.nRefCount--;
150  }
151  }
152  nNew--;
153 
154  assert(info.nRefCount == 0);
155 
156  // which tried bucket to move the entry to
157  int nKBucket = info.GetTriedBucket(nKey);
158  int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
159 
160  // first make space to add it (the existing tried entry there is moved to new, deleting whatever is there).
161  if (vvTried[nKBucket][nKBucketPos] != -1) {
162  // find an item to evict
163  int nIdEvict = vvTried[nKBucket][nKBucketPos];
164  assert(mapInfo.count(nIdEvict) == 1);
165  CAddrInfo& infoOld = mapInfo[nIdEvict];
166 
167  // Remove the to-be-evicted item from the tried set.
168  infoOld.fInTried = false;
169  vvTried[nKBucket][nKBucketPos] = -1;
170  nTried--;
171 
172  // find which new bucket it belongs to
173  int nUBucket = infoOld.GetNewBucket(nKey);
174  int nUBucketPos = infoOld.GetBucketPosition(nKey, true, nUBucket);
175  ClearNew(nUBucket, nUBucketPos);
176  assert(vvNew[nUBucket][nUBucketPos] == -1);
177 
178  // Enter it into the new set again.
179  infoOld.nRefCount = 1;
180  vvNew[nUBucket][nUBucketPos] = nIdEvict;
181  nNew++;
182  }
183  assert(vvTried[nKBucket][nKBucketPos] == -1);
184 
185  vvTried[nKBucket][nKBucketPos] = nId;
186  nTried++;
187  info.fInTried = true;
188 }
189 
190 void CAddrMan::Good_(const CService& addr, bool test_before_evict, int64_t nTime)
191 {
192  int nId;
193 
194  nLastGood = nTime;
195 
196  CAddrInfo* pinfo = Find(addr, &nId);
197 
198  // if not found, bail out
199  if (!pinfo)
200  return;
201 
202  CAddrInfo& info = *pinfo;
203 
204  // check whether we are talking about the exact same CService (including same port)
205  if (info != addr)
206  return;
207 
208  // update info
209  info.nLastSuccess = nTime;
210  info.nLastTry = nTime;
211  info.nAttempts = 0;
212  // nTime is not updated here, to avoid leaking information about
213  // currently-connected peers.
214 
215  // if it is already in the tried set, don't do anything else
216  if (info.fInTried)
217  return;
218 
219  // find a bucket it is in now
221  int nUBucket = -1;
222  for (unsigned int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
223  int nB = (n + nRnd) % ADDRMAN_NEW_BUCKET_COUNT;
224  int nBpos = info.GetBucketPosition(nKey, true, nB);
225  if (vvNew[nB][nBpos] == nId) {
226  nUBucket = nB;
227  break;
228  }
229  }
230 
231  // if no bucket is found, something bad happened;
232  // TODO: maybe re-add the node, but for now, just bail out
233  if (nUBucket == -1)
234  return;
235 
236  // which tried bucket to move the entry to
237  int tried_bucket = info.GetTriedBucket(nKey);
238  int tried_bucket_pos = info.GetBucketPosition(nKey, false, tried_bucket);
239 
240  // Will moving this address into tried evict another entry?
241  if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) {
242  LogPrint(BCLog::ADDRMAN, "Collision inserting element into tried table, moving %s to m_tried_collisions=%d\n", addr.ToString(), m_tried_collisions.size());
244  m_tried_collisions.insert(nId);
245  }
246  } else {
247  LogPrint(BCLog::ADDRMAN, "Moving %s to tried\n", addr.ToString());
248 
249  // move nId to the tried tables
250  MakeTried(info, nId);
251  }
252 }
253 
254 bool CAddrMan::Add_(const CAddress& addr, const CNetAddr& source, int64_t nTimePenalty)
255 {
256  if (!addr.IsRoutable())
257  return false;
258 
259  bool fNew = false;
260  int nId;
261  CAddrInfo* pinfo = Find(addr, &nId);
262 
263  // Do not set a penalty for a source's self-announcement
264  if (addr == source) {
265  nTimePenalty = 0;
266  }
267 
268  if (pinfo) {
269  // periodically update nTime
270  bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
271  int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
272  if (addr.nTime && (!pinfo->nTime || pinfo->nTime < addr.nTime - nUpdateInterval - nTimePenalty))
273  pinfo->nTime = std::max((int64_t)0, addr.nTime - nTimePenalty);
274 
275  // add services
276  pinfo->nServices = ServiceFlags(pinfo->nServices | addr.nServices);
277 
278  // do not update if no new information is present
279  if (!addr.nTime || (pinfo->nTime && addr.nTime <= pinfo->nTime))
280  return false;
281 
282  // do not update if the entry was already in the "tried" table
283  if (pinfo->fInTried)
284  return false;
285 
286  // do not update if the max reference count is reached
288  return false;
289 
290  // stochastic test: previous nRefCount == N: 2^N times harder to increase it
291  int nFactor = 1;
292  for (int n = 0; n < pinfo->nRefCount; n++)
293  nFactor *= 2;
294  if (nFactor > 1 && (RandomInt(nFactor) != 0))
295  return false;
296  } else {
297  pinfo = Create(addr, source, &nId);
298  pinfo->nTime = std::max((int64_t)0, (int64_t)pinfo->nTime - nTimePenalty);
299  nNew++;
300  fNew = true;
301  }
302 
303  int nUBucket = pinfo->GetNewBucket(nKey, source);
304  int nUBucketPos = pinfo->GetBucketPosition(nKey, true, nUBucket);
305  if (vvNew[nUBucket][nUBucketPos] != nId) {
306  bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
307  if (!fInsert) {
308  CAddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
309  if (infoExisting.IsTerrible() || (infoExisting.nRefCount > 1 && pinfo->nRefCount == 0)) {
310  // Overwrite the existing new table entry.
311  fInsert = true;
312  }
313  }
314  if (fInsert) {
315  ClearNew(nUBucket, nUBucketPos);
316  pinfo->nRefCount++;
317  vvNew[nUBucket][nUBucketPos] = nId;
318  } else {
319  if (pinfo->nRefCount == 0) {
320  Delete(nId);
321  }
322  }
323  }
324  return fNew;
325 }
326 
327 void CAddrMan::Attempt_(const CService& addr, bool fCountFailure, int64_t nTime)
328 {
329  CAddrInfo* pinfo = Find(addr);
330 
331  // if not found, bail out
332  if (!pinfo)
333  return;
334 
335  CAddrInfo& info = *pinfo;
336 
337  // check whether we are talking about the exact same CService (including same port)
338  if (info != addr)
339  return;
340 
341  // update info
342  info.nLastTry = nTime;
343  if (fCountFailure && info.nLastCountAttempt < nLastGood) {
344  info.nLastCountAttempt = nTime;
345  info.nAttempts++;
346  }
347 }
348 
350 {
351  if (size() == 0)
352  return CAddrInfo();
353 
354  if (newOnly && nNew == 0)
355  return CAddrInfo();
356 
357  // Use a 50% chance for choosing between tried and new table entries.
358  if (!newOnly &&
359  (nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
360  // use a tried node
361  double fChanceFactor = 1.0;
362  while (1) {
363  int nKBucket = RandomInt(ADDRMAN_TRIED_BUCKET_COUNT);
364  int nKBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
365  while (vvTried[nKBucket][nKBucketPos] == -1) {
367  nKBucketPos = (nKBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE;
368  }
369  int nId = vvTried[nKBucket][nKBucketPos];
370  assert(mapInfo.count(nId) == 1);
371  CAddrInfo& info = mapInfo[nId];
372  if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
373  return info;
374  fChanceFactor *= 1.2;
375  }
376  } else {
377  // use a new node
378  double fChanceFactor = 1.0;
379  while (1) {
380  int nUBucket = RandomInt(ADDRMAN_NEW_BUCKET_COUNT);
381  int nUBucketPos = RandomInt(ADDRMAN_BUCKET_SIZE);
382  while (vvNew[nUBucket][nUBucketPos] == -1) {
384  nUBucketPos = (nUBucketPos + insecure_rand.randbits(ADDRMAN_BUCKET_SIZE_LOG2)) % ADDRMAN_BUCKET_SIZE;
385  }
386  int nId = vvNew[nUBucket][nUBucketPos];
387  assert(mapInfo.count(nId) == 1);
388  CAddrInfo& info = mapInfo[nId];
389  if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
390  return info;
391  fChanceFactor *= 1.2;
392  }
393  }
394 }
395 
396 #ifdef DEBUG_ADDRMAN
397 int CAddrMan::Check_()
398 {
399  std::set<int> setTried;
400  std::map<int, int> mapNew;
401 
402  if (vRandom.size() != (size_t)(nTried + nNew))
403  return -7;
404 
405  for (const auto& entry : mapInfo) {
406  int n = entry.first;
407  const CAddrInfo& info = entry.second;
408  if (info.fInTried) {
409  if (!info.nLastSuccess)
410  return -1;
411  if (info.nRefCount)
412  return -2;
413  setTried.insert(n);
414  } else {
415  if (info.nRefCount < 0 || info.nRefCount > ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
416  return -3;
417  if (!info.nRefCount)
418  return -4;
419  mapNew[n] = info.nRefCount;
420  }
421  if (mapAddr[info] != n)
422  return -5;
423  if (info.nRandomPos < 0 || (size_t)info.nRandomPos >= vRandom.size() || vRandom[info.nRandomPos] != n)
424  return -14;
425  if (info.nLastTry < 0)
426  return -6;
427  if (info.nLastSuccess < 0)
428  return -8;
429  }
430 
431  if (setTried.size() != (size_t)nTried)
432  return -9;
433  if (mapNew.size() != (size_t)nNew)
434  return -10;
435 
436  for (int n = 0; n < ADDRMAN_TRIED_BUCKET_COUNT; n++) {
437  for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
438  if (vvTried[n][i] != -1) {
439  if (!setTried.count(vvTried[n][i]))
440  return -11;
441  if (mapInfo[vvTried[n][i]].GetTriedBucket(nKey) != n)
442  return -17;
443  if (mapInfo[vvTried[n][i]].GetBucketPosition(nKey, false, n) != i)
444  return -18;
445  setTried.erase(vvTried[n][i]);
446  }
447  }
448  }
449 
450  for (int n = 0; n < ADDRMAN_NEW_BUCKET_COUNT; n++) {
451  for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
452  if (vvNew[n][i] != -1) {
453  if (!mapNew.count(vvNew[n][i]))
454  return -12;
455  if (mapInfo[vvNew[n][i]].GetBucketPosition(nKey, true, n) != i)
456  return -19;
457  if (--mapNew[vvNew[n][i]] == 0)
458  mapNew.erase(vvNew[n][i]);
459  }
460  }
461  }
462 
463  if (setTried.size())
464  return -13;
465  if (mapNew.size())
466  return -15;
467  if (nKey.IsNull())
468  return -16;
469 
470  return 0;
471 }
472 #endif
473 
474 void CAddrMan::GetAddr_(std::vector<CAddress>& vAddr)
475 {
476  unsigned int nNodes = ADDRMAN_GETADDR_MAX_PCT * vRandom.size() / 100;
477  if (nNodes > ADDRMAN_GETADDR_MAX)
478  nNodes = ADDRMAN_GETADDR_MAX;
479 
480  // gather a list of random nodes, skipping those of low quality
481  for (unsigned int n = 0; n < vRandom.size(); n++) {
482  if (vAddr.size() >= nNodes)
483  break;
484 
485  int nRndPos = RandomInt(vRandom.size() - n) + n;
486  SwapRandom(n, nRndPos);
487  assert(mapInfo.count(vRandom[n]) == 1);
488 
489  const CAddrInfo& ai = mapInfo[vRandom[n]];
490  if (!ai.IsTerrible())
491  vAddr.push_back(ai);
492  }
493 }
494 
495 void CAddrMan::Connected_(const CService& addr, int64_t nTime)
496 {
497  CAddrInfo* pinfo = Find(addr);
498 
499  // if not found, bail out
500  if (!pinfo)
501  return;
502 
503  CAddrInfo& info = *pinfo;
504 
505  // check whether we are talking about the exact same CService (including same port)
506  if (info != addr)
507  return;
508 
509  // update info
510  int64_t nUpdateInterval = 20 * 60;
511  if (nTime - info.nTime > nUpdateInterval)
512  info.nTime = nTime;
513 }
514 
515 void CAddrMan::SetServices_(const CService& addr, ServiceFlags nServices)
516 {
517  CAddrInfo* pinfo = Find(addr);
518 
519  // if not found, bail out
520  if (!pinfo)
521  return;
522 
523  CAddrInfo& info = *pinfo;
524 
525  // check whether we are talking about the exact same CService (including same port)
526  if (info != addr)
527  return;
528 
529  // update info
530  info.nServices = nServices;
531 }
532 
533 int CAddrMan::RandomInt(int nMax){
534  return GetRandInt(nMax);
535 }
536 
538 {
539  for (std::set<int>::iterator it = m_tried_collisions.begin(); it != m_tried_collisions.end();) {
540  int id_new = *it;
541 
542  bool erase_collision = false;
543 
544  // If id_new not found in mapInfo remove it from m_tried_collisions
545  if (mapInfo.count(id_new) != 1) {
546  erase_collision = true;
547  } else {
548  CAddrInfo& info_new = mapInfo[id_new];
549 
550  // Which tried bucket to move the entry to.
551  int tried_bucket = info_new.GetTriedBucket(nKey);
552  int tried_bucket_pos = info_new.GetBucketPosition(nKey, false, tried_bucket);
553  if (!info_new.IsValid()) { // id_new may no longer map to a valid address
554  erase_collision = true;
555  } else if (vvTried[tried_bucket][tried_bucket_pos] != -1) { // The position in the tried bucket is not empty
556 
557  // Get the to-be-evicted address that is being tested
558  int id_old = vvTried[tried_bucket][tried_bucket_pos];
559  CAddrInfo& info_old = mapInfo[id_old];
560 
561  // Has successfully connected in last X hours
562  if (GetAdjustedTime() - info_old.nLastSuccess < ADDRMAN_REPLACEMENT_HOURS*(60*60)) {
563  erase_collision = true;
564  } else if (GetAdjustedTime() - info_old.nLastTry < ADDRMAN_REPLACEMENT_HOURS*(60*60)) { // attempted to connect and failed in last X hours
565 
566  // Give address at least 60 seconds to successfully connect
567  if (GetAdjustedTime() - info_old.nLastTry > 60) {
568  LogPrint(BCLog::ADDRMAN, "Swapping %s for %s in tried table\n", info_new.ToString(), info_old.ToString());
569 
570  // Replaces an existing address already in the tried table with the new address
571  Good_(info_new, false, GetAdjustedTime());
572  erase_collision = true;
573  }
574  }
575  } else { // Collision is not actually a collision anymore
576  Good_(info_new, false, GetAdjustedTime());
577  erase_collision = true;
578  }
579  }
580 
581  if (erase_collision) {
582  m_tried_collisions.erase(it++);
583  } else {
584  it++;
585  }
586  }
587 }
588 
590 {
591  if (m_tried_collisions.size() == 0) return CAddrInfo();
592 
593  std::set<int>::iterator it = m_tried_collisions.begin();
594 
595  // Selects a random element from m_tried_collisions
596  std::advance(it, GetRandInt(m_tried_collisions.size()));
597  int id_new = *it;
598 
599  // If id_new not found in mapInfo remove it from m_tried_collisions
600  if (mapInfo.count(id_new) != 1) {
601  m_tried_collisions.erase(it);
602  return CAddrInfo();
603  }
604 
605  CAddrInfo& newInfo = mapInfo[id_new];
606 
607  // which tried bucket to move the entry to
608  int tried_bucket = newInfo.GetTriedBucket(nKey);
609  int tried_bucket_pos = newInfo.GetBucketPosition(nKey, false, tried_bucket);
610 
611  int id_old = vvTried[tried_bucket][tried_bucket_pos];
612 
613  return mapInfo[id_old];
614 }
int nRefCount
reference count in new sets (memory only)
Definition: addrman.h:46
uint64_t randbits(int bits)
Generate a random (bits)-bit integer.
Definition: random.h:89
ServiceFlags
nServices flags
Definition: protocol.h:247
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:537
#define ADDRMAN_SET_TRIED_COLLISION_SIZE
the maximum number of tried addr collisions to store
Definition: addrman.h:183
int GetRandInt(int nMax)
Definition: random.cpp:369
#define ADDRMAN_TRIED_BUCKET_COUNT_LOG2
Stochastic address manager.
Definition: addrman.h:139
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:81
#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:148
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update an entry&#39;s service bits.
Definition: addrman.cpp:515
void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Delete an entry. It must not be in tried, and have refcount 0.
Definition: addrman.cpp:113
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:190
#define ADDRMAN_MIN_FAIL_DAYS
... in at least this many days
Definition: addrman.h:166
#define ADDRMAN_REPLACEMENT_HOURS
how recent a successful connection should be before we allow an address to be evicted from tried ...
Definition: addrman.h:169
void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry as attempted to connect.
Definition: addrman.cpp:327
int nAttempts
connection attempts since last successful attempt
Definition: addrman.h:43
#define ADDRMAN_NEW_BUCKET_COUNT_LOG2
total number of buckets for new addresses
Definition: addrman.h:142
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:254
std::set< int > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries. Test-before-evict disciplin...
Definition: addrman.h:223
virtual int RandomInt(int nMax)
Wraps GetRandInt to allow tests to override RandomInt and make it determinismistic.
Definition: addrman.cpp:533
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) EXCLUSIVE_LOCKS_REQUIRED(cs)
Swap two elements in vRandom.
Definition: addrman.cpp:93
int nRandomPos
position in vRandom
Definition: addrman.h:52
CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs)
Return a random to-be-evicted tried table address.
Definition: addrman.cpp:589
#define ADDRMAN_TRIED_BUCKET_COUNT
Convenience.
Definition: addrman.h:178
bool fInTried
in tried set? (memory only)
Definition: addrman.h:49
bool IsNull() const
Definition: uint256.h:32
bool IsValid() const
Definition: netaddress.cpp:188
std::vector< unsigned char > GetGroup() const
Definition: netaddress.cpp:312
Extended statistics about a CAddress.
Definition: addrman.h:24
const char * source
Definition: rpcconsole.cpp:54
int GetNewBucket(const uint256 &nKey, const CNetAddr &src) const
Calculate in which "new" bucket this entry belongs, given a certain source.
Definition: addrman.cpp:19
int GetTriedBucket(const uint256 &nKey) const
Calculate in which "tried" bucket this entry belongs.
Definition: addrman.cpp:12
#define ADDRMAN_BUCKET_SIZE_LOG2
maximum allowed number of entries in buckets for new and tried addresses
Definition: addrman.h:145
#define ADDRMAN_RETRIES
after how many failed attempts we give up on a new node
Definition: addrman.h:160
FastRandomContext insecure_rand
Source of random numbers for randomization in inner loops.
Definition: addrman.h:230
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:142
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:142
A CService with information about it as peer.
Definition: protocol.h:328
std::vector< unsigned char > GetKey() const
Definition: netaddress.cpp:550
#define ADDRMAN_BUCKET_SIZE
Definition: addrman.h:180
bool IsRoutable() const
Definition: netaddress.cpp:227
uint64_t GetHash() const
Definition: netaddress.cpp:385
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:33
void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs)
Clear a position in a "new" table. This is the only place where entries are actually deleted...
Definition: addrman.cpp:127
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:32
#define ADDRMAN_GETADDR_MAX
the maximum number of nodes to return in a getaddr call
Definition: addrman.h:175
size_t size() const
Return the number of (unique) addresses in all tables.
Definition: addrman.h:507
256-bit opaque blob.
Definition: uint256.h:122
unsigned int nTime
Definition: protocol.h:360
ServiceFlags nServices
Definition: protocol.h:357
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:349
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
Definition: addrman.cpp:27
void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry as currently-connected-to.
Definition: addrman.cpp:495
#define ADDRMAN_NEW_BUCKET_COUNT
Definition: addrman.h:179
int64_t GetAdjustedTime()
Definition: timedata.cpp:35
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:53
int64_t nLastCountAttempt
last counted attempt (memory only)
Definition: addrman.h:33
void GetAddr_(std::vector< CAddress > &vAddr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Select several addresses at once.
Definition: addrman.cpp:474
A writer stream (for serialization) that computes a 256-bit SHA-3-256 hash.
Definition: hash.h:165
std::string ToString() const
Definition: netaddress.cpp:574
uint256 nKey
secret key to randomize bucket select with
Definition: addrman.h:227
#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:151
#define ADDRMAN_HORIZON_DAYS
how old addresses can maximally be
Definition: addrman.h:157
#define ADDRMAN_MAX_FAILURES
how many successive failures are allowed ...
Definition: addrman.h:163
int64_t nLastSuccess
last successful connection by us
Definition: addrman.h:40
#define ADDRMAN_GETADDR_MAX_PCT
the maximum percentage of nodes to return in a getaddr call
Definition: addrman.h:172
int64_t nLastTry
last try whatsoever by us (memory only)
Definition: addrman.h:30
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS
in how many buckets for entries with new addresses a single address may occur
Definition: addrman.h:154
CAddrInfo * Find(const CNetAddr &addr, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Find an entry.
Definition: addrman.cpp:68