Bitcoin Core  0.20.99
P2P Digital Currency
addrman.h
Go to the documentation of this file.
1 // Copyright (c) 2012 Pieter Wuille
2 // Copyright (c) 2012-2020 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 #ifndef BITCOIN_ADDRMAN_H
7 #define BITCOIN_ADDRMAN_H
8 
9 #include <clientversion.h>
10 #include <netaddress.h>
11 #include <protocol.h>
12 #include <random.h>
13 #include <sync.h>
14 #include <timedata.h>
15 #include <util/system.h>
16 
17 #include <fs.h>
18 #include <hash.h>
19 #include <iostream>
20 #include <map>
21 #include <set>
22 #include <stdint.h>
23 #include <streams.h>
24 #include <vector>
25 
29 class CAddrInfo : public CAddress
30 {
31 public:
33  int64_t nLastTry{0};
34 
36  int64_t nLastCountAttempt{0};
37 
38 private:
41 
43  int64_t nLastSuccess{0};
44 
46  int nAttempts{0};
47 
49  int nRefCount{0};
50 
52  bool fInTried{false};
53 
55  int nRandomPos{-1};
56 
57  friend class CAddrMan;
58 
59 public:
60 
62  {
63  READWRITEAS(CAddress, obj);
64  READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
65  }
66 
67  CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
68  {
69  }
70 
71  CAddrInfo() : CAddress(), source()
72  {
73  }
74 
76  int GetTriedBucket(const uint256 &nKey, const std::vector<bool> &asmap) const;
77 
79  int GetNewBucket(const uint256 &nKey, const CNetAddr& src, const std::vector<bool> &asmap) const;
80 
82  int GetNewBucket(const uint256 &nKey, const std::vector<bool> &asmap) const
83  {
84  return GetNewBucket(nKey, source, asmap);
85  }
86 
88  int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const;
89 
91  bool IsTerrible(int64_t nNow = GetAdjustedTime()) const;
92 
94  double GetChance(int64_t nNow = GetAdjustedTime()) const;
95 };
96 
123 #define ADDRMAN_TRIED_BUCKET_COUNT_LOG2 8
125 
127 #define ADDRMAN_NEW_BUCKET_COUNT_LOG2 10
128 
130 #define ADDRMAN_BUCKET_SIZE_LOG2 6
131 
133 #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8
134 
136 #define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 64
137 
139 #define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 8
140 
142 #define ADDRMAN_HORIZON_DAYS 30
143 
145 #define ADDRMAN_RETRIES 3
146 
148 #define ADDRMAN_MAX_FAILURES 10
149 
151 #define ADDRMAN_MIN_FAIL_DAYS 7
152 
154 #define ADDRMAN_REPLACEMENT_HOURS 4
155 
157 #define ADDRMAN_TRIED_BUCKET_COUNT (1 << ADDRMAN_TRIED_BUCKET_COUNT_LOG2)
158 #define ADDRMAN_NEW_BUCKET_COUNT (1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2)
159 #define ADDRMAN_BUCKET_SIZE (1 << ADDRMAN_BUCKET_SIZE_LOG2)
160 
162 #define ADDRMAN_SET_TRIED_COLLISION_SIZE 10
163 
165 static const int64_t ADDRMAN_TEST_WINDOW = 40*60; // 40 minutes
166 
170 class CAddrMan
171 {
172 friend class CAddrManTest;
173 protected:
176 
177 private:
179  int nIdCount GUARDED_BY(cs);
180 
182  std::map<int, CAddrInfo> mapInfo GUARDED_BY(cs);
183 
185  std::map<CNetAddr, int> mapAddr GUARDED_BY(cs);
186 
188  std::vector<int> vRandom GUARDED_BY(cs);
189 
190  // number of "tried" entries
191  int nTried GUARDED_BY(cs);
192 
195 
197  int nNew GUARDED_BY(cs);
198 
201 
203  int64_t nLastGood GUARDED_BY(cs);
204 
206  std::set<int> m_tried_collisions;
207 
208 protected:
211 
214 
216  CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
217 
220  CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
221 
223  void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) EXCLUSIVE_LOCKS_REQUIRED(cs);
224 
226  void MakeTried(CAddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
227 
229  void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
230 
232  void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs);
233 
235  void Good_(const CService &addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
236 
238  bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
239 
241  void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
242 
244  CAddrInfo Select_(bool newOnly) EXCLUSIVE_LOCKS_REQUIRED(cs);
245 
247  void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
248 
250  CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
251 
252 #ifdef DEBUG_ADDRMAN
253  int Check_() EXCLUSIVE_LOCKS_REQUIRED(cs);
255 #endif
256 
258  void GetAddr_(std::vector<CAddress> &vAddr, size_t max_addresses, size_t max_pct) EXCLUSIVE_LOCKS_REQUIRED(cs);
259 
261  void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
262 
264  void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
265 
266 public:
267  // Compressed IP->ASN mapping, loaded from a file when a node starts.
268  // Should be always empty if no file was provided.
269  // This mapping is then used for bucketing nodes in Addrman.
270  //
271  // If asmap is provided, nodes will be bucketed by
272  // AS they belong to, in order to make impossible for a node
273  // to connect to several nodes hosted in a single AS.
274  // This is done in response to Erebus attack, but also to generally
275  // diversify the connections every node creates,
276  // especially useful when a large fraction of nodes
277  // operate under a couple of cloud providers.
278  //
279  // If a new asmap was provided, the existing records
280  // would be re-bucketed accordingly.
281  std::vector<bool> m_asmap;
282 
283  // Read asmap from provided binary file
284  static std::vector<bool> DecodeAsmap(fs::path path);
285 
286 
316  template<typename Stream>
317  void Serialize(Stream &s) const
318  {
319  LOCK(cs);
320 
321  unsigned char nVersion = 2;
322  s << nVersion;
323  s << ((unsigned char)32);
324  s << nKey;
325  s << nNew;
326  s << nTried;
327 
328  int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
329  s << nUBuckets;
330  std::map<int, int> mapUnkIds;
331  int nIds = 0;
332  for (const auto& entry : mapInfo) {
333  mapUnkIds[entry.first] = nIds;
334  const CAddrInfo &info = entry.second;
335  if (info.nRefCount) {
336  assert(nIds != nNew); // this means nNew was wrong, oh ow
337  s << info;
338  nIds++;
339  }
340  }
341  nIds = 0;
342  for (const auto& entry : mapInfo) {
343  const CAddrInfo &info = entry.second;
344  if (info.fInTried) {
345  assert(nIds != nTried); // this means nTried was wrong, oh ow
346  s << info;
347  nIds++;
348  }
349  }
350  for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
351  int nSize = 0;
352  for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
353  if (vvNew[bucket][i] != -1)
354  nSize++;
355  }
356  s << nSize;
357  for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
358  if (vvNew[bucket][i] != -1) {
359  int nIndex = mapUnkIds[vvNew[bucket][i]];
360  s << nIndex;
361  }
362  }
363  }
364  // Store asmap version after bucket entries so that it
365  // can be ignored by older clients for backward compatibility.
366  uint256 asmap_version;
367  if (m_asmap.size() != 0) {
368  asmap_version = SerializeHash(m_asmap);
369  }
370  s << asmap_version;
371  }
372 
373  template<typename Stream>
374  void Unserialize(Stream& s)
375  {
376  LOCK(cs);
377 
378  Clear();
379  unsigned char nVersion;
380  s >> nVersion;
381  unsigned char nKeySize;
382  s >> nKeySize;
383  if (nKeySize != 32) throw std::ios_base::failure("Incorrect keysize in addrman deserialization");
384  s >> nKey;
385  s >> nNew;
386  s >> nTried;
387  int nUBuckets = 0;
388  s >> nUBuckets;
389  if (nVersion != 0) {
390  nUBuckets ^= (1 << 30);
391  }
392 
394  throw std::ios_base::failure("Corrupt CAddrMan serialization, nNew exceeds limit.");
395  }
396 
397  if (nTried > ADDRMAN_TRIED_BUCKET_COUNT * ADDRMAN_BUCKET_SIZE) {
398  throw std::ios_base::failure("Corrupt CAddrMan serialization, nTried exceeds limit.");
399  }
400 
401  // Deserialize entries from the new table.
402  for (int n = 0; n < nNew; n++) {
403  CAddrInfo &info = mapInfo[n];
404  s >> info;
405  mapAddr[info] = n;
406  info.nRandomPos = vRandom.size();
407  vRandom.push_back(n);
408  }
409  nIdCount = nNew;
410 
411  // Deserialize entries from the tried table.
412  int nLost = 0;
413  for (int n = 0; n < nTried; n++) {
414  CAddrInfo info;
415  s >> info;
416  int nKBucket = info.GetTriedBucket(nKey, m_asmap);
417  int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
418  if (vvTried[nKBucket][nKBucketPos] == -1) {
419  info.nRandomPos = vRandom.size();
420  info.fInTried = true;
421  vRandom.push_back(nIdCount);
422  mapInfo[nIdCount] = info;
423  mapAddr[info] = nIdCount;
424  vvTried[nKBucket][nKBucketPos] = nIdCount;
425  nIdCount++;
426  } else {
427  nLost++;
428  }
429  }
430  nTried -= nLost;
431 
432  // Store positions in the new table buckets to apply later (if possible).
433  std::map<int, int> entryToBucket; // Represents which entry belonged to which bucket when serializing
434 
435  for (int bucket = 0; bucket < nUBuckets; bucket++) {
436  int nSize = 0;
437  s >> nSize;
438  for (int n = 0; n < nSize; n++) {
439  int nIndex = 0;
440  s >> nIndex;
441  if (nIndex >= 0 && nIndex < nNew) {
442  entryToBucket[nIndex] = bucket;
443  }
444  }
445  }
446 
447  uint256 supplied_asmap_version;
448  if (m_asmap.size() != 0) {
449  supplied_asmap_version = SerializeHash(m_asmap);
450  }
451  uint256 serialized_asmap_version;
452  if (nVersion > 1) {
453  s >> serialized_asmap_version;
454  }
455 
456  for (int n = 0; n < nNew; n++) {
457  CAddrInfo &info = mapInfo[n];
458  int bucket = entryToBucket[n];
459  int nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
460  if (nVersion == 2 && nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && vvNew[bucket][nUBucketPos] == -1 &&
461  info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS && serialized_asmap_version == supplied_asmap_version) {
462  // Bucketing has not changed, using existing bucket positions for the new table
463  vvNew[bucket][nUBucketPos] = n;
464  info.nRefCount++;
465  } else {
466  // In case the new table data cannot be used (nVersion unknown, bucket count wrong or new asmap),
467  // try to give them a reference based on their primary source address.
468  LogPrint(BCLog::ADDRMAN, "Bucketing method was updated, re-bucketing addrman entries from disk\n");
469  bucket = info.GetNewBucket(nKey, m_asmap);
470  nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
471  if (vvNew[bucket][nUBucketPos] == -1) {
472  vvNew[bucket][nUBucketPos] = n;
473  info.nRefCount++;
474  }
475  }
476  }
477 
478  // Prune new entries with refcount 0 (as a result of collisions).
479  int nLostUnk = 0;
480  for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); ) {
481  if (it->second.fInTried == false && it->second.nRefCount == 0) {
482  std::map<int, CAddrInfo>::const_iterator itCopy = it++;
483  Delete(itCopy->first);
484  nLostUnk++;
485  } else {
486  it++;
487  }
488  }
489  if (nLost + nLostUnk > 0) {
490  LogPrint(BCLog::ADDRMAN, "addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
491  }
492 
493  Check();
494  }
495 
496  void Clear()
497  {
498  LOCK(cs);
499  std::vector<int>().swap(vRandom);
500  nKey = insecure_rand.rand256();
501  for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
502  for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
503  vvNew[bucket][entry] = -1;
504  }
505  }
506  for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; bucket++) {
507  for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
508  vvTried[bucket][entry] = -1;
509  }
510  }
511 
512  nIdCount = 0;
513  nTried = 0;
514  nNew = 0;
515  nLastGood = 1; //Initially at 1 so that "never" is strictly worse.
516  mapInfo.clear();
517  mapAddr.clear();
518  }
519 
521  {
522  Clear();
523  }
524 
526  {
527  nKey.SetNull();
528  }
529 
531  size_t size() const
532  {
533  LOCK(cs); // TODO: Cache this in an atomic to avoid this overhead
534  return vRandom.size();
535  }
536 
538  void Check()
539  {
540 #ifdef DEBUG_ADDRMAN
541  {
542  LOCK(cs);
543  int err;
544  if ((err=Check_()))
545  LogPrintf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
546  }
547 #endif
548  }
549 
551  bool Add(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty = 0)
552  {
553  LOCK(cs);
554  bool fRet = false;
555  Check();
556  fRet |= Add_(addr, source, nTimePenalty);
557  Check();
558  if (fRet) {
559  LogPrint(BCLog::ADDRMAN, "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort(), source.ToString(), nTried, nNew);
560  }
561  return fRet;
562  }
563 
565  bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty = 0)
566  {
567  LOCK(cs);
568  int nAdd = 0;
569  Check();
570  for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
571  nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
572  Check();
573  if (nAdd) {
574  LogPrint(BCLog::ADDRMAN, "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString(), nTried, nNew);
575  }
576  return nAdd > 0;
577  }
578 
580  void Good(const CService &addr, bool test_before_evict = true, int64_t nTime = GetAdjustedTime())
581  {
582  LOCK(cs);
583  Check();
584  Good_(addr, test_before_evict, nTime);
585  Check();
586  }
587 
589  void Attempt(const CService &addr, bool fCountFailure, int64_t nTime = GetAdjustedTime())
590  {
591  LOCK(cs);
592  Check();
593  Attempt_(addr, fCountFailure, nTime);
594  Check();
595  }
596 
599  {
600  LOCK(cs);
601  Check();
602  ResolveCollisions_();
603  Check();
604  }
605 
608  {
609  CAddrInfo ret;
610  {
611  LOCK(cs);
612  Check();
613  ret = SelectTriedCollision_();
614  Check();
615  }
616  return ret;
617  }
618 
622  CAddrInfo Select(bool newOnly = false)
623  {
624  CAddrInfo addrRet;
625  {
626  LOCK(cs);
627  Check();
628  addrRet = Select_(newOnly);
629  Check();
630  }
631  return addrRet;
632  }
633 
635  std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct)
636  {
637  Check();
638  std::vector<CAddress> vAddr;
639  {
640  LOCK(cs);
641  GetAddr_(vAddr, max_addresses, max_pct);
642  }
643  Check();
644  return vAddr;
645  }
646 
648  void Connected(const CService &addr, int64_t nTime = GetAdjustedTime())
649  {
650  LOCK(cs);
651  Check();
652  Connected_(addr, nTime);
653  Check();
654  }
655 
657  {
658  LOCK(cs);
659  Check();
660  SetServices_(addr, nServices);
661  Check();
662  }
663 
664 };
665 
666 #endif // BITCOIN_ADDRMAN_H
int nRefCount
reference count in new sets (memory only)
Definition: addrman.h:49
ServiceFlags
nServices flags
Definition: protocol.h:257
CAddrInfo Select(bool newOnly=false)
Choose an address to connect to.
Definition: addrman.h:622
void SetNull()
Definition: uint256.h:38
#define LogPrint(category,...)
Definition: logging.h:182
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime=GetAdjustedTime())
Mark an entry as connection attempted to.
Definition: addrman.h:589
int GetTriedBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "tried" bucket this entry belongs.
Definition: addrman.cpp:12
~CAddrMan()
Definition: addrman.h:525
int nAttempts
connection attempts since last successful attempt
Definition: addrman.h:46
uint256 rand256() noexcept
generate a random uint256.
Definition: random.cpp:616
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:166
static const int64_t ADDRMAN_TEST_WINDOW
the maximum time we&#39;ll spend trying to resolve a tried table collision, in seconds ...
Definition: addrman.h:165
std::set< int > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries. Test-before-evict disciplin...
Definition: addrman.h:206
std::string ToString() const
Definition: netaddress.cpp:355
int nRandomPos
position in vRandom
Definition: addrman.h:55
bool Add(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty=0)
Add a single address.
Definition: addrman.h:551
#define ADDRMAN_TRIED_BUCKET_COUNT
Convenience.
Definition: addrman.h:157
#define READWRITEAS(type, obj)
Definition: serialize.h:172
bool fInTried
in tried set? (memory only)
Definition: addrman.h:52
Stochastical (IP) address manager.
Definition: addrman.h:170
RecursiveMutex cs
critical section to protect the inner data structures
Definition: addrman.h:175
uint256 SerializeHash(const T &obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Compute the 256-bit hash of an object&#39;s serialization.
Definition: hash.h:191
Extended statistics about a CAddress.
Definition: addrman.h:29
FastRandomContext insecure_rand
Source of random numbers for randomization in inner loops.
Definition: addrman.h:213
void Unserialize(Stream &s)
Definition: addrman.h:374
#define LOCK(cs)
Definition: sync.h:230
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:308
Fast randomness source.
Definition: random.h:119
void Check()
Consistency check.
Definition: addrman.h:538
int GetNewBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "new" bucket this entry belongs, using its default source.
Definition: addrman.h:82
A CService with information about it as peer.
Definition: protocol.h:348
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:22
#define ADDRMAN_BUCKET_SIZE
Definition: addrman.h:159
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:39
CAddrInfo()
Definition: addrman.h:71
Network address.
Definition: netaddress.h:91
size_t size() const
Return the number of (unique) addresses in all tables.
Definition: addrman.h:531
256-bit opaque blob.
Definition: uint256.h:123
ServiceFlags nServices
Definition: protocol.h:380
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
Definition: addrman.cpp:33
SERIALIZE_METHODS(CAddrInfo, obj)
Definition: addrman.h:61
void Clear()
Definition: addrman.h:496
CAddrMan()
Definition: addrman.h:520
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
Definition: addrman.h:67
#define ADDRMAN_NEW_BUCKET_COUNT
Definition: addrman.h:158
int64_t GetAdjustedTime()
Definition: timedata.cpp:34
CAddrInfo SelectTriedCollision()
Randomly select an address in tried that another address is attempting to evict.
Definition: addrman.h:607
std::string ToStringIPPort() const
Definition: netaddress.cpp:743
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:59
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct)
Return a bunch of addresses, selected at random.
Definition: addrman.h:635
int64_t nLastCountAttempt
last counted attempt (memory only)
Definition: addrman.h:36
void ResolveCollisions()
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions...
Definition: addrman.h:598
#define GUARDED_BY(x)
Definition: threadsafety.h:38
std::vector< bool > m_asmap
Definition: addrman.h:281
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Add multiple addresses.
Definition: addrman.h:565
void Good(const CService &addr, bool test_before_evict=true, int64_t nTime=GetAdjustedTime())
Mark an entry as accessible.
Definition: addrman.h:580
void SetServices(const CService &addr, ServiceFlags nServices)
Definition: addrman.h:656
uint256 nKey
secret key to randomize bucket select with
Definition: addrman.h:210
void Serialize(Stream &s) const
serialized format:
Definition: addrman.h:317
#define READWRITE(...)
Definition: serialize.h:171
void Connected(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as currently-connected-to.
Definition: addrman.h:648
auto it
Definition: validation.cpp:381
uint32_t nTime
Definition: protocol.h:378
int64_t nLastSuccess
last successful connection by us
Definition: addrman.h:43
int64_t nLastTry
last try whatsoever by us (memory only)
Definition: addrman.h:33
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS
in how many buckets for entries with new addresses a single address may occur
Definition: addrman.h:139
CNetAddr source
where knowledge about this address first came from
Definition: addrman.h:40