Feathercoin  0.5.0
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
addrman.h
Go to the documentation of this file.
1 // Copyright (c) 2012 Pieter Wuille
2 // Distributed under the MIT/X11 software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 #ifndef _BITCOIN_ADDRMAN
5 #define _BITCOIN_ADDRMAN 1
6 
7 #include "netbase.h"
8 #include "protocol.h"
9 #include "util.h"
10 #include "sync.h"
11 
12 
13 #include <map>
14 #include <vector>
15 
16 #include <openssl/rand.h>
17 
18 
20 class CAddrInfo : public CAddress
21 {
22 private:
23  // where knowledge about this address first came from
25 
26  // last successful connection by us
28 
29  // last try whatsoever by us:
30  // int64 CAddress::nLastTry
31 
32  // connection attempts since last successful attempt
33  int nAttempts;
34 
35  // reference count in new sets (memory only)
36  int nRefCount;
37 
38  // in tried set? (memory only)
39  bool fInTried;
40 
41  // position in vRandom
43 
44  friend class CAddrMan;
45 
46 public:
47 
49  CAddress* pthis = (CAddress*)(this);
50  READWRITE(*pthis);
51  READWRITE(source);
52  READWRITE(nLastSuccess);
53  READWRITE(nAttempts);
54  )
55 
56  void Init()
57  {
58  nLastSuccess = 0;
59  nLastTry = 0;
60  nAttempts = 0;
61  nRefCount = 0;
62  fInTried = false;
63  nRandomPos = -1;
64  }
65 
66  CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource) : CAddress(addrIn), source(addrSource)
67  {
68  Init();
69  }
70 
71  CAddrInfo() : CAddress(), source()
72  {
73  Init();
74  }
75 
76  // Calculate in which "tried" bucket this entry belongs
77  int GetTriedBucket(const std::vector<unsigned char> &nKey) const;
78 
79  // Calculate in which "new" bucket this entry belongs, given a certain source
80  int GetNewBucket(const std::vector<unsigned char> &nKey, const CNetAddr& src) const;
81 
82  // Calculate in which "new" bucket this entry belongs, using its default source
83  int GetNewBucket(const std::vector<unsigned char> &nKey) const
84  {
85  return GetNewBucket(nKey, source);
86  }
87 
88  // Determine whether the statistics about this entry are bad enough so that it can just be deleted
89  bool IsTerrible(int64 nNow = GetAdjustedTime()) const;
90 
91  // Calculate the relative chance this entry should be given when selecting nodes to connect to
92  double GetChance(int64 nNow = GetAdjustedTime()) const;
93 
94 };
95 
96 // Stochastic address manager
97 //
98 // Design goals:
99 // * Only keep a limited number of addresses around, so that addr.dat and memory requirements do not grow without bound.
100 // * Keep the address tables in-memory, and asynchronously dump the entire to able in addr.dat.
101 // * Make sure no (localized) attacker can fill the entire table with his nodes/addresses.
102 //
103 // To that end:
104 // * Addresses are organized into buckets.
105 // * Address that have not yet been tried go into 256 "new" buckets.
106 // * Based on the address range (/16 for IPv4) of source of the information, 32 buckets are selected at random
107 // * The actual bucket is chosen from one of these, based on the range the address itself is located.
108 // * One single address can occur in up to 4 different buckets, to increase selection chances for addresses that
109 // are seen frequently. The chance for increasing this multiplicity decreases exponentially.
110 // * When adding a new address to a full bucket, a randomly chosen entry (with a bias favoring less recently seen
111 // ones) is removed from it first.
112 // * Addresses of nodes that are known to be accessible go into 64 "tried" buckets.
113 // * Each address range selects at random 4 of these buckets.
114 // * The actual bucket is chosen from one of these, based on the full address.
115 // * When adding a new good address to a full bucket, a randomly chosen entry (with a bias favoring less recently
116 // tried ones) is evicted from it, back to the "new" buckets.
117 // * Bucket selection is based on cryptographic hashing, using a randomly-generated 256-bit key, which should not
118 // be observable by adversaries.
119 // * Several indexes are kept for high performance. Defining DEBUG_ADDRMAN will introduce frequent (and expensive)
120 // consistency checks for the entire data structure.
121 
122 // total number of buckets for tried addresses
123 #define ADDRMAN_TRIED_BUCKET_COUNT 64
124 
125 // maximum allowed number of entries in buckets for tried addresses
126 #define ADDRMAN_TRIED_BUCKET_SIZE 64
127 
128 // total number of buckets for new addresses
129 #define ADDRMAN_NEW_BUCKET_COUNT 256
130 
131 // maximum allowed number of entries in buckets for new addresses
132 #define ADDRMAN_NEW_BUCKET_SIZE 64
133 
134 // over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread
135 #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 4
136 
137 // over how many buckets entries with new addresses originating from a single group are spread
138 #define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 32
139 
140 // in how many buckets for entries with new addresses a single address may occur
141 #define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 4
142 
143 // how many entries in a bucket with tried addresses are inspected, when selecting one to replace
144 #define ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT 4
145 
146 // how old addresses can maximally be
147 #define ADDRMAN_HORIZON_DAYS 30
148 
149 // after how many failed attempts we give up on a new node
150 #define ADDRMAN_RETRIES 3
151 
152 // how many successive failures are allowed ...
153 #define ADDRMAN_MAX_FAILURES 10
154 
155 // ... in at least this many days
156 #define ADDRMAN_MIN_FAIL_DAYS 7
157 
158 // the maximum percentage of nodes to return in a getaddr call
159 #define ADDRMAN_GETADDR_MAX_PCT 23
160 
161 // the maximum number of nodes to return in a getaddr call
162 #define ADDRMAN_GETADDR_MAX 2500
163 
165 class CAddrMan
166 {
167 private:
168  // critical section to protect the inner data structures
170 
171  // secret key to randomize bucket select with
172  std::vector<unsigned char> nKey;
173 
174  // last used nId
175  int nIdCount;
176 
177  // table with information about all nIds
178  std::map<int, CAddrInfo> mapInfo;
179 
180  // find an nId based on its network address
181  std::map<CNetAddr, int> mapAddr;
182 
183  // randomly-ordered vector of all nIds
184  std::vector<int> vRandom;
185 
186  // number of "tried" entries
187  int nTried;
188 
189  // list of "tried" buckets
190  std::vector<std::vector<int> > vvTried;
191 
192  // number of (unique) "new" entries
193  int nNew;
194 
195  // list of "new" buckets
196  std::vector<std::set<int> > vvNew;
197 
198 protected:
199 
200  // Find an entry.
201  CAddrInfo* Find(const CNetAddr& addr, int *pnId = NULL);
202 
203  // find an entry, creating it if necessary.
204  // nTime and nServices of found node is updated, if necessary.
205  CAddrInfo* Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId = NULL);
206 
207  // Swap two elements in vRandom.
208  void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2);
209 
210  // Return position in given bucket to replace.
211  int SelectTried(int nKBucket);
212 
213  // Remove an element from a "new" bucket.
214  // This is the only place where actual deletes occur.
215  // They are never deleted while in the "tried" table, only possibly evicted back to the "new" table.
216  int ShrinkNew(int nUBucket);
217 
218  // Move an entry from the "new" table(s) to the "tried" table
219  // @pre vvUnkown[nOrigin].count(nId) != 0
220  void MakeTried(CAddrInfo& info, int nId, int nOrigin);
221 
222  // Mark an entry "good", possibly moving it from "new" to "tried".
223  void Good_(const CService &addr, int64 nTime);
224 
225  // Add an entry to the "new" table.
226  bool Add_(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty);
227 
228  // Mark an entry as attempted to connect.
229  void Attempt_(const CService &addr, int64 nTime);
230 
231  // Select an address to connect to.
232  // nUnkBias determines how much to favor new addresses over tried ones (min=0, max=100)
233  CAddress Select_(int nUnkBias);
234 
235 #ifdef DEBUG_ADDRMAN
236  // Perform consistency check. Returns an error code or zero.
237  int Check_();
238 #endif
239 
240  // Select several addresses at once.
241  void GetAddr_(std::vector<CAddress> &vAddr);
242 
243  // Mark an entry as currently-connected-to.
244  void Connected_(const CService &addr, int64 nTime);
245 
246 public:
247 
249  (({
250  // serialized format:
251  // * version byte (currently 0)
252  // * nKey
253  // * nNew
254  // * nTried
255  // * number of "new" buckets
256  // * all nNew addrinfos in vvNew
257  // * all nTried addrinfos in vvTried
258  // * for each bucket:
259  // * number of elements
260  // * for each element: index
261  //
262  // Notice that vvTried, mapAddr and vVector are never encoded explicitly;
263  // they are instead reconstructed from the other information.
264  //
265  // vvNew is serialized, but only used if ADDRMAN_UNKOWN_BUCKET_COUNT didn't change,
266  // otherwise it is reconstructed as well.
267  //
268  // This format is more complex, but significantly smaller (at most 1.5 MiB), and supports
269  // changes to the ADDRMAN_ parameters without breaking the on-disk structure.
270  {
271  LOCK(cs);
272  unsigned char nVersion = 0;
273  READWRITE(nVersion);
274  READWRITE(nKey);
275  READWRITE(nNew);
276  READWRITE(nTried);
277 
278  CAddrMan *am = const_cast<CAddrMan*>(this);
279  if (fWrite)
280  {
281  int nUBuckets = ADDRMAN_NEW_BUCKET_COUNT;
282  READWRITE(nUBuckets);
283  std::map<int, int> mapUnkIds;
284  int nIds = 0;
285  for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
286  {
287  if (nIds == nNew) break; // this means nNew was wrong, oh ow
288  mapUnkIds[(*it).first] = nIds;
289  CAddrInfo &info = (*it).second;
290  if (info.nRefCount)
291  {
292  READWRITE(info);
293  nIds++;
294  }
295  }
296  nIds = 0;
297  for (std::map<int, CAddrInfo>::iterator it = am->mapInfo.begin(); it != am->mapInfo.end(); it++)
298  {
299  if (nIds == nTried) break; // this means nTried was wrong, oh ow
300  CAddrInfo &info = (*it).second;
301  if (info.fInTried)
302  {
303  READWRITE(info);
304  nIds++;
305  }
306  }
307  for (std::vector<std::set<int> >::iterator it = am->vvNew.begin(); it != am->vvNew.end(); it++)
308  {
309  const std::set<int> &vNew = (*it);
310  int nSize = vNew.size();
311  READWRITE(nSize);
312  for (std::set<int>::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++)
313  {
314  int nIndex = mapUnkIds[*it2];
315  READWRITE(nIndex);
316  }
317  }
318  } else {
319  int nUBuckets = 0;
320  READWRITE(nUBuckets);
321  am->nIdCount = 0;
322  am->mapInfo.clear();
323  am->mapAddr.clear();
324  am->vRandom.clear();
325  am->vvTried = std::vector<std::vector<int> >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0));
326  am->vvNew = std::vector<std::set<int> >(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>());
327  for (int n = 0; n < am->nNew; n++)
328  {
329  CAddrInfo &info = am->mapInfo[n];
330  READWRITE(info);
331  am->mapAddr[info] = n;
332  info.nRandomPos = vRandom.size();
333  am->vRandom.push_back(n);
334  if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
335  {
336  am->vvNew[info.GetNewBucket(am->nKey)].insert(n);
337  info.nRefCount++;
338  }
339  }
340  am->nIdCount = am->nNew;
341  int nLost = 0;
342  for (int n = 0; n < am->nTried; n++)
343  {
344  CAddrInfo info;
345  READWRITE(info);
346  std::vector<int> &vTried = am->vvTried[info.GetTriedBucket(am->nKey)];
347  if (vTried.size() < ADDRMAN_TRIED_BUCKET_SIZE)
348  {
349  info.nRandomPos = vRandom.size();
350  info.fInTried = true;
351  am->vRandom.push_back(am->nIdCount);
352  am->mapInfo[am->nIdCount] = info;
353  am->mapAddr[info] = am->nIdCount;
354  vTried.push_back(am->nIdCount);
355  am->nIdCount++;
356  } else {
357  nLost++;
358  }
359  }
360  am->nTried -= nLost;
361  for (int b = 0; b < nUBuckets; b++)
362  {
363  std::set<int> &vNew = am->vvNew[b];
364  int nSize = 0;
365  READWRITE(nSize);
366  for (int n = 0; n < nSize; n++)
367  {
368  int nIndex = 0;
369  READWRITE(nIndex);
370  CAddrInfo &info = am->mapInfo[nIndex];
371  if (nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS)
372  {
373  info.nRefCount++;
374  vNew.insert(nIndex);
375  }
376  }
377  }
378  }
379  }
380  });)
381 
382  CAddrMan() : vRandom(0), vvTried(ADDRMAN_TRIED_BUCKET_COUNT, std::vector<int>(0)), vvNew(ADDRMAN_NEW_BUCKET_COUNT, std::set<int>())
383  {
384  nKey.resize(32);
385  RAND_bytes(&nKey[0], 32);
386 
387  nIdCount = 0;
388  nTried = 0;
389  nNew = 0;
390  }
391 
392  // Return the number of (unique) addresses in all tables.
393  int size()
394  {
395  return vRandom.size();
396  }
397 
398  // Consistency check
399  void Check()
400  {
401 #ifdef DEBUG_ADDRMAN
402  {
403  LOCK(cs);
404  int err;
405  if ((err=Check_()))
406  printf("ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
407  }
408 #endif
409  }
410 
411  // Add a single address.
412  bool Add(const CAddress &addr, const CNetAddr& source, int64 nTimePenalty = 0)
413  {
414  bool fRet = false;
415  {
416  LOCK(cs);
417  Check();
418  fRet |= Add_(addr, source, nTimePenalty);
419  Check();
420  }
421  if (fRet)
422  printf("Added %s from %s: %i tried, %i new\n", addr.ToStringIPPort().c_str(), source.ToString().c_str(), nTried, nNew);
423  return fRet;
424  }
425 
426  // Add multiple addresses.
427  bool Add(const std::vector<CAddress> &vAddr, const CNetAddr& source, int64 nTimePenalty = 0)
428  {
429  int nAdd = 0;
430  {
431  LOCK(cs);
432  Check();
433  for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
434  nAdd += Add_(*it, source, nTimePenalty) ? 1 : 0;
435  Check();
436  }
437  if (nAdd)
438  printf("Added %i addresses from %s: %i tried, %i new\n", nAdd, source.ToString().c_str(), nTried, nNew);
439  return nAdd > 0;
440  }
441 
442  // Mark an entry as accessible.
443  void Good(const CService &addr, int64 nTime = GetAdjustedTime())
444  {
445  {
446  LOCK(cs);
447  Check();
448  Good_(addr, nTime);
449  Check();
450  }
451  }
452 
453  // Mark an entry as connection attempted to.
454  void Attempt(const CService &addr, int64 nTime = GetAdjustedTime())
455  {
456  {
457  LOCK(cs);
458  Check();
459  Attempt_(addr, nTime);
460  Check();
461  }
462  }
463 
464  // Choose an address to connect to.
465  // nUnkBias determines how much "new" entries are favored over "tried" ones (0-100).
466  CAddress Select(int nUnkBias = 50)
467  {
468  CAddress addrRet;
469  {
470  LOCK(cs);
471  Check();
472  addrRet = Select_(nUnkBias);
473  Check();
474  }
475  return addrRet;
476  }
477 
478  // Return a bunch of addresses, selected at random.
479  std::vector<CAddress> GetAddr()
480  {
481  Check();
482  std::vector<CAddress> vAddr;
483  {
484  LOCK(cs);
485  GetAddr_(vAddr);
486  }
487  Check();
488  return vAddr;
489  }
490 
491  // Mark an entry as currently-connected-to.
492  void Connected(const CService &addr, int64 nTime = GetAdjustedTime())
493  {
494  {
495  LOCK(cs);
496  Check();
497  Connected_(addr, nTime);
498  Check();
499  }
500  }
501 };
502 
503 #endif
int nRefCount
Definition: addrman.h:36
int GetNewBucket(const std::vector< unsigned char > &nKey, const CNetAddr &src) const
Definition: addrman.cpp:24
bool Add_(const CAddress &addr, const CNetAddr &source, int64 nTimePenalty)
Definition: addrman.cpp:313
#define READWRITE(obj)
Definition: serialize.h:93
void Init()
Definition: protocol.cpp:91
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=NULL)
Definition: addrman.cpp:94
std::string ToStringIPPort() const
Definition: netbase.cpp:1117
int nAttempts
Definition: addrman.h:33
CAddress Select_(int nUnkBias)
Definition: addrman.cpp:390
bool Add(const CAddress &addr, const CNetAddr &source, int64 nTimePenalty=0)
Definition: addrman.h:412
int64 nLastSuccess
Definition: addrman.h:27
int nRandomPos
Definition: addrman.h:42
#define ADDRMAN_TRIED_BUCKET_COUNT
Definition: addrman.h:123
bool fInTried
Definition: addrman.h:39
CAddrInfo * Find(const CNetAddr &addr, int *pnId=NULL)
Definition: addrman.cpp:81
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64 nTimePenalty=0)
Definition: addrman.h:427
Stochastical (IP) address manager.
Definition: addrman.h:165
std::vector< CAddress > GetAddr()
Definition: addrman.h:479
Extended statistics about a CAddress.
Definition: addrman.h:20
std::vector< int > vRandom
Definition: addrman.h:184
int SelectTried(int nKBucket)
Definition: addrman.cpp:126
std::vector< std::set< int > > vvNew
Definition: addrman.h:196
#define printf
Definition: rpcdump.cpp:12
#define LOCK(cs)
Definition: sync.h:108
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netbase.h:90
void MakeTried(CAddrInfo &info, int nId, int nOrigin)
Definition: addrman.cpp:204
void Check()
Definition: addrman.h:399
int64 GetAdjustedTime()
Definition: util.cpp:1317
A CService with information about it as peer.
Definition: protocol.h:76
int nTried
Definition: addrman.h:187
double GetChance(int64 nNow=GetAdjustedTime()) const
Definition: addrman.cpp:58
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2)
Definition: addrman.cpp:106
int64 nLastTry
Definition: protocol.h:109
void Attempt(const CService &addr, int64 nTime=GetAdjustedTime())
Definition: addrman.h:454
void Connected_(const CService &addr, int64 nTime)
Definition: addrman.cpp:510
int nIdCount
Definition: addrman.h:175
int ShrinkNew(int nUBucket)
Definition: addrman.cpp:150
std::map< CNetAddr, int > mapAddr
Definition: addrman.h:181
IMPLEMENT_SERIALIZE(CAddress *pthis=(CAddress *)(this);READWRITE(*pthis);READWRITE(source);READWRITE(nLastSuccess);READWRITE(nAttempts);) void Init()
Definition: addrman.h:48
CAddrInfo()
Definition: addrman.h:71
void Connected(const CService &addr, int64 nTime=GetAdjustedTime())
Definition: addrman.h:492
#define ADDRMAN_TRIED_BUCKET_SIZE
Definition: addrman.h:126
std::vector< std::vector< int > > vvTried
Definition: addrman.h:190
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
Definition: netbase.h:34
int size()
Definition: addrman.h:393
void Good_(const CService &addr, int64 nTime)
Definition: addrman.cpp:262
bool IsTerrible(int64 nNow=GetAdjustedTime()) const
Definition: addrman.cpp:38
std::vector< unsigned char > nKey
Definition: addrman.h:172
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
Definition: addrman.h:66
#define ADDRMAN_NEW_BUCKET_COUNT
Definition: addrman.h:129
int GetTriedBucket(const std::vector< unsigned char > &nKey) const
Definition: addrman.cpp:10
void Good(const CService &addr, int64 nTime=GetAdjustedTime())
Definition: addrman.h:443
CAddress Select(int nUnkBias=50)
Definition: addrman.h:466
void GetAddr_(std::vector< CAddress > &vAddr)
Definition: addrman.cpp:494
void Attempt_(const CService &addr, int64 nTime)
Definition: addrman.cpp:371
std::map< int, CAddrInfo > mapInfo
Definition: addrman.h:178
int GetNewBucket(const std::vector< unsigned char > &nKey) const
Definition: addrman.h:83
std::string ToString() const
Definition: netbase.cpp:777
int nNew
Definition: addrman.h:193
CCriticalSection cs
Definition: addrman.h:169
IMPLEMENT_SERIALIZE(({{LOCK(cs);unsigned char nVersion=0;READWRITE(nVersion);READWRITE(nKey);READWRITE(nNew);READWRITE(nTried);CAddrMan *am=const_cast< CAddrMan * >(this);if(fWrite){int nUBuckets=ADDRMAN_NEW_BUCKET_COUNT;READWRITE(nUBuckets);std::map< int, int > mapUnkIds;int nIds=0;for(std::map< int, CAddrInfo >::iterator it=am->mapInfo.begin();it!=am->mapInfo.end();it++){if(nIds==nNew) break;mapUnkIds[(*it).first]=nIds;CAddrInfo &info=(*it).second;if(info.nRefCount){READWRITE(info);nIds++;}}nIds=0;for(std::map< int, CAddrInfo >::iterator it=am->mapInfo.begin();it!=am->mapInfo.end();it++){if(nIds==nTried) break;CAddrInfo &info=(*it).second;if(info.fInTried){READWRITE(info);nIds++;}}for(std::vector< std::set< int > >::iterator it=am->vvNew.begin();it!=am->vvNew.end();it++){const std::set< int > &vNew=(*it);int nSize=vNew.size();READWRITE(nSize);for(std::set< int >::iterator it2=vNew.begin();it2!=vNew.end();it2++){int nIndex=mapUnkIds[*it2];READWRITE(nIndex);}}}else{int nUBuckets=0;READWRITE(nUBuckets);am->nIdCount=0;am->mapInfo.clear();am->mapAddr.clear();am->vRandom.clear();am->vvTried=std::vector< std::vector< int > >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector< int >(0));am->vvNew=std::vector< std::set< int > >(ADDRMAN_NEW_BUCKET_COUNT, std::set< int >());for(int n=0;n< am->nNew;n++){CAddrInfo &info=am->mapInfo[n];READWRITE(info);am->mapAddr[info]=n;info.nRandomPos=vRandom.size();am->vRandom.push_back(n);if(nUBuckets!=ADDRMAN_NEW_BUCKET_COUNT){am->vvNew[info.GetNewBucket(am->nKey)].insert(n);info.nRefCount++;}}am->nIdCount=am->nNew;int nLost=0;for(int n=0;n< am->nTried;n++){CAddrInfo info;READWRITE(info);std::vector< int > &vTried=am->vvTried[info.GetTriedBucket(am->nKey)];if(vTried.size()< ADDRMAN_TRIED_BUCKET_SIZE){info.nRandomPos=vRandom.size();info.fInTried=true;am->vRandom.push_back(am->nIdCount);am->mapInfo[am->nIdCount]=info;am->mapAddr[info]=am->nIdCount;vTried.push_back(am->nIdCount);am->nIdCount++;}else{nLost++;}}am->nTried-=nLost;for(int b=0;b< nUBuckets;b++){std::set< int > &vNew=am->vvNew[b];int nSize=0;READWRITE(nSize);for(int n=0;n< nSize;n++){int nIndex=0;READWRITE(nIndex);CAddrInfo &info=am->mapInfo[nIndex];if(nUBuckets==ADDRMAN_NEW_BUCKET_COUNT &&info.nRefCount< ADDRMAN_NEW_BUCKETS_PER_ADDRESS){info.nRefCount++;vNew.insert(nIndex);}}}}}});) CAddrMan()
Definition: addrman.h:249
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS
Definition: addrman.h:141
CNetAddr source
Definition: addrman.h:24
long long int64
Definition: serialize.h:25