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