22 std::vector<unsigned char> vchSourceGroupKey = src.
GetGroup();
39 if (
nTime > nNow + 10 * 60)
57 int64_t nSinceLastTry = std::max<int64_t>(nNow -
nLastTry, 0);
60 if (nSinceLastTry < 60 * 10)
64 fChance *= pow(0.66, std::min(
nAttempts, 8));
71 std::map<CNetAddr, int>::iterator it = mapAddr.find(addr);
72 if (it == mapAddr.end())
76 std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
77 if (it2 != mapInfo.end())
78 return &(*it2).second;
84 if ((mapInfo.count(nId) == 0) || (nId < mapInfo.count(nId) - 1))
92 mapInfo[nId] =
CAddrInfo(addr, addrSource);
94 mapInfo[nId].nRandomPos = vRandom.size();
95 vRandom.push_back(nId);
103 if (nRndPos1 == nRndPos2)
106 assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
108 int nId1 = vRandom[nRndPos1];
109 int nId2 = vRandom[nRndPos2];
111 assert(mapInfo.count(nId1) == 1);
112 assert(mapInfo.count(nId2) == 1);
114 mapInfo[nId1].nRandomPos = nRndPos2;
115 mapInfo[nId2].nRandomPos = nRndPos1;
117 vRandom[nRndPos1] = nId2;
118 vRandom[nRndPos2] = nId1;
123 assert(mapInfo.count(nId) != 0);
125 assert(!info.fInTried);
126 assert(info.nRefCount == 0);
128 SwapRandom(info.nRandomPos, vRandom.size() - 1);
138 if (vvNew[nUBucket][nUBucketPos] != -1) {
139 int nIdDelete = vvNew[nUBucket][nUBucketPos];
140 CAddrInfo& infoDelete = mapInfo[nIdDelete];
143 vvNew[nUBucket][nUBucketPos] = -1;
155 if (vvNew[bucket][pos] == nId) {
156 vvNew[bucket][pos] = -1;
169 if (vvTried[nKBucket][nKBucketPos] != -1) {
171 int nIdEvict = vvTried[nKBucket][nKBucketPos];
172 assert(mapInfo.count(nIdEvict) == 1);
177 vvTried[nKBucket][nKBucketPos] = -1;
181 int nUBucket = infoOld.GetNewBucket(nKey);
182 int nUBucketPos = infoOld.GetBucketPosition(nKey,
true, nUBucket);
183 ClearNew(nUBucket, nUBucketPos);
184 assert(vvNew[nUBucket][nUBucketPos] == -1);
187 infoOld.nRefCount = 1;
188 vvNew[nUBucket][nUBucketPos] = nIdEvict;
191 assert(vvTried[nKBucket][nKBucketPos] == -1);
193 vvTried[nKBucket][nKBucketPos] = nId;
231 int nB = (n + nRnd) % ADDRMAN_NEW_BUCKET_COUNT;
233 if (vvNew[nB][nBpos] == nId) {
247 MakeTried(info, nId);
260 if (addr == source) {
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);
288 for (
int n = 0; n < pinfo->
nRefCount; n++)
290 if (nFactor > 1 && (RandomInt(nFactor) != 0))
293 pinfo = Create(addr, source, &nId);
294 pinfo->
nTime = std::max((int64_t)0, (int64_t)pinfo->
nTime - nTimePenalty);
301 if (vvNew[nUBucket][nUBucketPos] != nId) {
302 bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
304 CAddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
311 ClearNew(nUBucket, nUBucketPos);
313 vvNew[nUBucket][nUBucketPos] = nId;
350 if (newOnly && nNew == 0)
355 (nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
357 double fChanceFactor = 1.0;
361 while (vvTried[nKBucket][nKBucketPos] == -1) {
365 int nId = vvTried[nKBucket][nKBucketPos];
366 assert(mapInfo.count(nId) == 1);
368 if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
370 fChanceFactor *= 1.2;
374 double fChanceFactor = 1.0;
378 while (vvNew[nUBucket][nUBucketPos] == -1) {
382 int nId = vvNew[nUBucket][nUBucketPos];
383 assert(mapInfo.count(nId) == 1);
385 if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
387 fChanceFactor *= 1.2;
393 int CAddrMan::Check_()
395 std::set<int> setTried;
396 std::map<int, int> mapNew;
398 if (vRandom.size() != nTried + nNew)
401 for (std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
417 if (mapAddr[info] != n)
427 if (setTried.size() != nTried)
429 if (mapNew.size() != nNew)
434 if (vvTried[n][i] != -1) {
435 if (!setTried.count(vvTried[n][i]))
441 setTried.erase(vvTried[n][i]);
448 if (vvNew[n][i] != -1) {
449 if (!mapNew.count(vvNew[n][i]))
453 if (--mapNew[vvNew[n][i]] == 0)
454 mapNew.erase(vvNew[n][i]);
477 for (
unsigned int n = 0; n < vRandom.size(); n++) {
478 if (vAddr.size() >= nNodes)
481 int nRndPos = RandomInt(vRandom.size() - n) + n;
482 SwapRandom(n, nRndPos);
483 assert(mapInfo.count(vRandom[n]) == 1);
485 const CAddrInfo& ai = mapInfo[vRandom[n]];
486 if (!ai.IsTerrible())
506 int64_t nUpdateInterval = 20 * 60;
507 if (nTime - info.
nTime > nUpdateInterval)
int nRefCount
reference count in new sets (memory only)
void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime)
Mark an entry as attempted to connect.
ServiceFlags
nServices flags
CAddrInfo * Find(const CNetAddr &addr, int *pnId=nullptr)
Find an entry.
#define ADDRMAN_TRIED_BUCKET_COUNT_LOG2
Stochastic address manager.
CAddrInfo Select_(bool newOnly)
Select an address to connect to, if newOnly is set to true, only the new table is selected from...
#define ADDRMAN_TRIED_BUCKETS_PER_GROUP
over how many buckets entries with tried addresses from a single group (/16 for IPv4) are spread ...
void SetServices_(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
#define ADDRMAN_MIN_FAIL_DAYS
... in at least this many days
int nAttempts
connection attempts since last successful attempt
#define ADDRMAN_NEW_BUCKET_COUNT_LOG2
total number of buckets for new addresses
virtual int RandomInt(int nMax)
Wraps GetRandInt to allow tests to override RandomInt and make it determinismistic.
int nRandomPos
position in vRandom
#define ADDRMAN_TRIED_BUCKET_COUNT
Convenience.
bool fInTried
in tried set? (memory only)
CAddrInfo * ById(unsigned long nId)
std::vector< unsigned char > GetGroup() const
Extended statistics about a CAddress.
int GetNewBucket(const uint256 &nKey, const CNetAddr &src) const
Calculate in which "new" bucket this entry belongs, given a certain source.
int GetTriedBucket(const uint256 &nKey) const
Calculate in which "tried" bucket this entry belongs.
#define ADDRMAN_BUCKET_SIZE_LOG2
maximum allowed number of entries in buckets for new and tried addresses
#define ADDRMAN_RETRIES
after how many failed attempts we give up on a new node
void MakeTried(CAddrInfo &info, int nId)
Move an entry from the "new" table(s) to the "tried" table.
A combination of a network address (CNetAddr) and a (TCP) port.
A CService with information about it as peer.
std::vector< unsigned char > GetKey() const
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2)
Swap two elements in vRandom.
#define ADDRMAN_BUCKET_SIZE
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr)
find an entry, creating it if necessary.
bool IsTerrible(int64_t nNow=GetAdjustedTime()) const
Determine whether the statistics about this entry are bad enough so that it can just be deleted...
#define LogPrint(category,...)
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
#define ADDRMAN_GETADDR_MAX
the maximum number of nodes to return in a getaddr call
void Good_(const CService &addr, int64_t nTime)
Mark an entry "good", possibly moving it from "new" to "tried".
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
#define ADDRMAN_NEW_BUCKET_COUNT
int64_t GetAdjustedTime()
bool Add_(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty)
Add an entry to the "new" table.
double GetChance(int64_t nNow=GetAdjustedTime()) const
Calculate the relative chance this entry should be given when selecting nodes to connect to...
void Connected_(const CService &addr, int64_t nTime)
Mark an entry as currently-connected-to.
int64_t nLastCountAttempt
last counted attempt (memory only)
void GetAddr_(std::vector< CAddress > &vAddr)
Select several addresses at once.
A writer stream (for serialization) that computes a 256-bit hash.
std::string ToString() const
void Delete(int nId)
Delete an entry. It must not be in tried, and have refcount 0.
#define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP
over how many buckets entries with new addresses originating from a single group are spread ...
#define ADDRMAN_HORIZON_DAYS
how old addresses can maximally be
#define ADDRMAN_MAX_FAILURES
how many successive failures are allowed ...
int64_t nLastSuccess
last successful connection by us
void ClearNew(int nUBucket, int nUBucketPos)
Clear a position in a "new" table. This is the only place where entries are actually deleted...
#define ADDRMAN_GETADDR_MAX_PCT
the maximum percentage of nodes to return in a getaddr call
int64_t nLastTry
last try whatsoever by us (memory only)
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS
in how many buckets for entries with new addresses a single address may occur
CNetAddr source
where knowledge about this address first came from