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_GETADDR_MAX_PCT 23
158 
160 #define ADDRMAN_GETADDR_MAX 2500
161 
163 #define ADDRMAN_TRIED_BUCKET_COUNT (1 << ADDRMAN_TRIED_BUCKET_COUNT_LOG2)
164 #define ADDRMAN_NEW_BUCKET_COUNT (1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2)
165 #define ADDRMAN_BUCKET_SIZE (1 << ADDRMAN_BUCKET_SIZE_LOG2)
166 
168 #define ADDRMAN_SET_TRIED_COLLISION_SIZE 10
169 
171 static const int64_t ADDRMAN_TEST_WINDOW = 40*60; // 40 minutes
172 
176 class CAddrMan
177 {
178 friend class CAddrManTest;
179 protected:
182 
183 private:
185  int nIdCount GUARDED_BY(cs);
186 
188  std::map<int, CAddrInfo> mapInfo GUARDED_BY(cs);
189 
191  std::map<CNetAddr, int> mapAddr GUARDED_BY(cs);
192 
194  std::vector<int> vRandom GUARDED_BY(cs);
195 
196  // number of "tried" entries
197  int nTried GUARDED_BY(cs);
198 
201 
203  int nNew GUARDED_BY(cs);
204 
207 
209  int64_t nLastGood GUARDED_BY(cs);
210 
212  std::set<int> m_tried_collisions;
213 
214 protected:
217 
220 
222  CAddrInfo* Find(const CNetAddr& addr, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
223 
226  CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
227 
229  void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) EXCLUSIVE_LOCKS_REQUIRED(cs);
230 
232  void MakeTried(CAddrInfo& info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
233 
235  void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
236 
238  void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs);
239 
241  void Good_(const CService &addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs);
242 
244  bool Add_(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
245 
247  void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
248 
250  CAddrInfo Select_(bool newOnly) EXCLUSIVE_LOCKS_REQUIRED(cs);
251 
253  void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs);
254 
256  CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs);
257 
258 #ifdef DEBUG_ADDRMAN
259  int Check_() EXCLUSIVE_LOCKS_REQUIRED(cs);
261 #endif
262 
264  void GetAddr_(std::vector<CAddress> &vAddr) EXCLUSIVE_LOCKS_REQUIRED(cs);
265 
267  void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs);
268 
270  void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
271 
272 public:
273  // Compressed IP->ASN mapping, loaded from a file when a node starts.
274  // Should be always empty if no file was provided.
275  // This mapping is then used for bucketing nodes in Addrman.
276  //
277  // If asmap is provided, nodes will be bucketed by
278  // AS they belong to, in order to make impossible for a node
279  // to connect to several nodes hosted in a single AS.
280  // This is done in response to Erebus attack, but also to generally
281  // diversify the connections every node creates,
282  // especially useful when a large fraction of nodes
283  // operate under a couple of cloud providers.
284  //
285  // If a new asmap was provided, the existing records
286  // would be re-bucketed accordingly.
287  std::vector<bool> m_asmap;
288 
289  // Read asmap from provided binary file
290  static std::vector<bool> DecodeAsmap(fs::path path);
291 
292 
322  template<typename Stream>
323  void Serialize(Stream &s) const
324  {
325  LOCK(cs);
326 
327  unsigned char nVersion = 2;
328  s << nVersion;
329  s << ((unsigned char)32);
330  s << nKey;
331  s << nNew;
332  s << nTried;
333 
334  int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30);
335  s << nUBuckets;
336  std::map<int, int> mapUnkIds;
337  int nIds = 0;
338  for (const auto& entry : mapInfo) {
339  mapUnkIds[entry.first] = nIds;
340  const CAddrInfo &info = entry.second;
341  if (info.nRefCount) {
342  assert(nIds != nNew); // this means nNew was wrong, oh ow
343  s << info;
344  nIds++;
345  }
346  }
347  nIds = 0;
348  for (const auto& entry : mapInfo) {
349  const CAddrInfo &info = entry.second;
350  if (info.fInTried) {
351  assert(nIds != nTried); // this means nTried was wrong, oh ow
352  s << info;
353  nIds++;
354  }
355  }
356  for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
357  int nSize = 0;
358  for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
359  if (vvNew[bucket][i] != -1)
360  nSize++;
361  }
362  s << nSize;
363  for (int i = 0; i < ADDRMAN_BUCKET_SIZE; i++) {
364  if (vvNew[bucket][i] != -1) {
365  int nIndex = mapUnkIds[vvNew[bucket][i]];
366  s << nIndex;
367  }
368  }
369  }
370  // Store asmap version after bucket entries so that it
371  // can be ignored by older clients for backward compatibility.
372  uint256 asmap_version;
373  if (m_asmap.size() != 0) {
374  asmap_version = SerializeHash(m_asmap);
375  }
376  s << asmap_version;
377  }
378 
379  template<typename Stream>
380  void Unserialize(Stream& s)
381  {
382  LOCK(cs);
383 
384  Clear();
385  unsigned char nVersion;
386  s >> nVersion;
387  unsigned char nKeySize;
388  s >> nKeySize;
389  if (nKeySize != 32) throw std::ios_base::failure("Incorrect keysize in addrman deserialization");
390  s >> nKey;
391  s >> nNew;
392  s >> nTried;
393  int nUBuckets = 0;
394  s >> nUBuckets;
395  if (nVersion != 0) {
396  nUBuckets ^= (1 << 30);
397  }
398 
400  throw std::ios_base::failure("Corrupt CAddrMan serialization, nNew exceeds limit.");
401  }
402 
403  if (nTried > ADDRMAN_TRIED_BUCKET_COUNT * ADDRMAN_BUCKET_SIZE) {
404  throw std::ios_base::failure("Corrupt CAddrMan serialization, nTried exceeds limit.");
405  }
406 
407  // Deserialize entries from the new table.
408  for (int n = 0; n < nNew; n++) {
409  CAddrInfo &info = mapInfo[n];
410  s >> info;
411  mapAddr[info] = n;
412  info.nRandomPos = vRandom.size();
413  vRandom.push_back(n);
414  }
415  nIdCount = nNew;
416 
417  // Deserialize entries from the tried table.
418  int nLost = 0;
419  for (int n = 0; n < nTried; n++) {
420  CAddrInfo info;
421  s >> info;
422  int nKBucket = info.GetTriedBucket(nKey, m_asmap);
423  int nKBucketPos = info.GetBucketPosition(nKey, false, nKBucket);
424  if (vvTried[nKBucket][nKBucketPos] == -1) {
425  info.nRandomPos = vRandom.size();
426  info.fInTried = true;
427  vRandom.push_back(nIdCount);
428  mapInfo[nIdCount] = info;
429  mapAddr[info] = nIdCount;
430  vvTried[nKBucket][nKBucketPos] = nIdCount;
431  nIdCount++;
432  } else {
433  nLost++;
434  }
435  }
436  nTried -= nLost;
437 
438  // Store positions in the new table buckets to apply later (if possible).
439  std::map<int, int> entryToBucket; // Represents which entry belonged to which bucket when serializing
440 
441  for (int bucket = 0; bucket < nUBuckets; bucket++) {
442  int nSize = 0;
443  s >> nSize;
444  for (int n = 0; n < nSize; n++) {
445  int nIndex = 0;
446  s >> nIndex;
447  if (nIndex >= 0 && nIndex < nNew) {
448  entryToBucket[nIndex] = bucket;
449  }
450  }
451  }
452 
453  uint256 supplied_asmap_version;
454  if (m_asmap.size() != 0) {
455  supplied_asmap_version = SerializeHash(m_asmap);
456  }
457  uint256 serialized_asmap_version;
458  if (nVersion > 1) {
459  s >> serialized_asmap_version;
460  }
461 
462  for (int n = 0; n < nNew; n++) {
463  CAddrInfo &info = mapInfo[n];
464  int bucket = entryToBucket[n];
465  int nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
466  if (nVersion == 2 && nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && vvNew[bucket][nUBucketPos] == -1 &&
467  info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS && serialized_asmap_version == supplied_asmap_version) {
468  // Bucketing has not changed, using existing bucket positions for the new table
469  vvNew[bucket][nUBucketPos] = n;
470  info.nRefCount++;
471  } else {
472  // In case the new table data cannot be used (nVersion unknown, bucket count wrong or new asmap),
473  // try to give them a reference based on their primary source address.
474  LogPrint(BCLog::ADDRMAN, "Bucketing method was updated, re-bucketing addrman entries from disk\n");
475  bucket = info.GetNewBucket(nKey, m_asmap);
476  nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
477  if (vvNew[bucket][nUBucketPos] == -1) {
478  vvNew[bucket][nUBucketPos] = n;
479  info.nRefCount++;
480  }
481  }
482  }
483 
484  // Prune new entries with refcount 0 (as a result of collisions).
485  int nLostUnk = 0;
486  for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end(); ) {
487  if (it->second.fInTried == false && it->second.nRefCount == 0) {
488  std::map<int, CAddrInfo>::const_iterator itCopy = it++;
489  Delete(itCopy->first);
490  nLostUnk++;
491  } else {
492  it++;
493  }
494  }
495  if (nLost + nLostUnk > 0) {
496  LogPrint(BCLog::ADDRMAN, "addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
497  }
498 
499  Check();
500  }
501 
502  void Clear()
503  {
504  LOCK(cs);
505  std::vector<int>().swap(vRandom);
506  nKey = insecure_rand.rand256();
507  for (size_t bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; bucket++) {
508  for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
509  vvNew[bucket][entry] = -1;
510  }
511  }
512  for (size_t bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; bucket++) {
513  for (size_t entry = 0; entry < ADDRMAN_BUCKET_SIZE; entry++) {
514  vvTried[bucket][entry] = -1;
515  }
516  }
517 
518  nIdCount = 0;
519  nTried = 0;
520  nNew = 0;
521  nLastGood = 1; //Initially at 1 so that "never" is strictly worse.
522  mapInfo.clear();
523  mapAddr.clear();
524  }
525 
527  {
528  Clear();
529  }
530 
532  {
533  nKey.SetNull();
534  }
535 
537  size_t size() const
538  {
539  LOCK(cs); // TODO: Cache this in an atomic to avoid this overhead
540  return vRandom.size();
541  }
542 
544  void Check()
545  {
546 #ifdef DEBUG_ADDRMAN
547  {
548  LOCK(cs);
549  int err;
550  if ((err=Check_()))
551  LogPrintf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
552  }
553 #endif
554  }
555 
557  bool Add(const CAddress &addr, const CNetAddr& source, int64_t nTimePenalty = 0)
558  {
559  LOCK(cs);
560  bool fRet = false;
561  Check();
562  fRet |= Add_(addr, source, nTimePenalty);
563  Check();
564  if (fRet) {
565  LogPrint(BCLog::ADDRMAN, "Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort(), source.ToString(), nTried, nNew);
566  }
567  return fRet;
568  }
569 
571  bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64_t nTimePenalty = 0)
572  {
573  LOCK(cs);
574  int nAdd = 0;
575  Check();
576  for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
577  nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
578  Check();
579  if (nAdd) {
580  LogPrint(BCLog::ADDRMAN, "Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString(), nTried, nNew);
581  }
582  return nAdd > 0;
583  }
584 
586  void Good(const CService &addr, bool test_before_evict = true, int64_t nTime = GetAdjustedTime())
587  {
588  LOCK(cs);
589  Check();
590  Good_(addr, test_before_evict, nTime);
591  Check();
592  }
593 
595  void Attempt(const CService &addr, bool fCountFailure, int64_t nTime = GetAdjustedTime())
596  {
597  LOCK(cs);
598  Check();
599  Attempt_(addr, fCountFailure, nTime);
600  Check();
601  }
602 
605  {
606  LOCK(cs);
607  Check();
608  ResolveCollisions_();
609  Check();
610  }
611 
614  {
615  CAddrInfo ret;
616  {
617  LOCK(cs);
618  Check();
619  ret = SelectTriedCollision_();
620  Check();
621  }
622  return ret;
623  }
624 
628  CAddrInfo Select(bool newOnly = false)
629  {
630  CAddrInfo addrRet;
631  {
632  LOCK(cs);
633  Check();
634  addrRet = Select_(newOnly);
635  Check();
636  }
637  return addrRet;
638  }
639 
641  std::vector<CAddress> GetAddr()
642  {
643  Check();
644  std::vector<CAddress> vAddr;
645  {
646  LOCK(cs);
647  GetAddr_(vAddr);
648  }
649  Check();
650  return vAddr;
651  }
652 
654  void Connected(const CService &addr, int64_t nTime = GetAdjustedTime())
655  {
656  LOCK(cs);
657  Check();
658  Connected_(addr, nTime);
659  Check();
660  }
661 
663  {
664  LOCK(cs);
665  Check();
666  SetServices_(addr, nServices);
667  Check();
668  }
669 
670 };
671 
672 #endif // BITCOIN_ADDRMAN_H
int nRefCount
reference count in new sets (memory only)
Definition: addrman.h:49
ServiceFlags
nServices flags
Definition: protocol.h:259
CAddrInfo Select(bool newOnly=false)
Choose an address to connect to.
Definition: addrman.h:628
void SetNull()
Definition: uint256.h:38
#define LogPrint(category,...)
Definition: logging.h:180
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime=GetAdjustedTime())
Mark an entry as connection attempted to.
Definition: addrman.h:595
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:531
int nAttempts
connection attempts since last successful attempt
Definition: addrman.h:46
uint256 rand256() noexcept
generate a random uint256.
Definition: random.cpp:610
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:164
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:171
std::set< int > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries. Test-before-evict disciplin...
Definition: addrman.h:212
std::string ToString() const
Definition: netaddress.cpp:357
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:557
#define ADDRMAN_TRIED_BUCKET_COUNT
Convenience.
Definition: addrman.h:163
#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:176
RecursiveMutex cs
critical section to protect the inner data structures
Definition: addrman.h:181
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:196
std::vector< CAddress > GetAddr()
Return a bunch of addresses, selected at random.
Definition: addrman.h:641
Extended statistics about a CAddress.
Definition: addrman.h:29
FastRandomContext insecure_rand
Source of random numbers for randomization in inner loops.
Definition: addrman.h:219
void Unserialize(Stream &s)
Definition: addrman.h:380
#define LOCK(cs)
Definition: sync.h:218
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:138
Fast randomness source.
Definition: random.h:119
void Check()
Consistency check.
Definition: addrman.h:544
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:340
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:165
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
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netaddress.h:31
size_t size() const
Return the number of (unique) addresses in all tables.
Definition: addrman.h:537
256-bit opaque blob.
Definition: uint256.h:120
ServiceFlags nServices
Definition: protocol.h:363
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:51
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:502
CAddrMan()
Definition: addrman.h:526
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
Definition: addrman.h:67
#define ADDRMAN_NEW_BUCKET_COUNT
Definition: addrman.h:164
int64_t GetAdjustedTime()
Definition: timedata.cpp:35
CAddrInfo SelectTriedCollision()
Randomly select an address in tried that another address is attempting to evict.
Definition: addrman.h:613
std::string ToStringIPPort() const
Definition: netaddress.cpp:741
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
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:604
#define GUARDED_BY(x)
Definition: threadsafety.h:38
std::vector< bool > m_asmap
Definition: addrman.h:287
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Add multiple addresses.
Definition: addrman.h:571
void Good(const CService &addr, bool test_before_evict=true, int64_t nTime=GetAdjustedTime())
Mark an entry as accessible.
Definition: addrman.h:586
void SetServices(const CService &addr, ServiceFlags nServices)
Definition: addrman.h:662
uint256 nKey
secret key to randomize bucket select with
Definition: addrman.h:216
void Serialize(Stream &s) const
serialized format:
Definition: addrman.h:323
#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:654
auto it
Definition: validation.cpp:380
uint32_t nTime
Definition: protocol.h:365
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