21 std::vector<unsigned char> vchSourceGroupKey = src.
GetGroup();
38 if (
nTime > nNow + 10 * 60)
56 int64_t nSinceLastTry = std::max<int64_t>(nNow -
nLastTry, 0);
59 if (nSinceLastTry < 60 * 10)
70 std::map<CNetAddr, int>::iterator it = mapAddr.find(addr);
71 if (it == mapAddr.end())
75 std::map<int, CAddrInfo>::iterator it2 = mapInfo.find((*it).second);
76 if (it2 != mapInfo.end())
77 return &(*it2).second;
84 mapInfo[nId] =
CAddrInfo(addr, addrSource);
86 mapInfo[nId].nRandomPos = vRandom.size();
87 vRandom.push_back(nId);
95 if (nRndPos1 == nRndPos2)
98 assert(nRndPos1 < vRandom.size() && nRndPos2 < vRandom.size());
100 int nId1 = vRandom[nRndPos1];
101 int nId2 = vRandom[nRndPos2];
103 assert(mapInfo.count(nId1) == 1);
104 assert(mapInfo.count(nId2) == 1);
106 mapInfo[nId1].nRandomPos = nRndPos2;
107 mapInfo[nId2].nRandomPos = nRndPos1;
109 vRandom[nRndPos1] = nId2;
110 vRandom[nRndPos2] = nId1;
115 assert(mapInfo.count(nId) != 0);
118 assert(info.nRefCount == 0);
120 SwapRandom(info.nRandomPos, vRandom.size() - 1);
130 if (vvNew[nUBucket][nUBucketPos] != -1) {
131 int nIdDelete = vvNew[nUBucket][nUBucketPos];
132 CAddrInfo& infoDelete = mapInfo[nIdDelete];
135 vvNew[nUBucket][nUBucketPos] = -1;
147 if (vvNew[
bucket][pos] == nId) {
161 if (vvTried[nKBucket][nKBucketPos] != -1) {
163 int nIdEvict = vvTried[nKBucket][nKBucketPos];
164 assert(mapInfo.count(nIdEvict) == 1);
169 vvTried[nKBucket][nKBucketPos] = -1;
173 int nUBucket = infoOld.GetNewBucket(nKey);
174 int nUBucketPos = infoOld.GetBucketPosition(nKey,
true, nUBucket);
175 ClearNew(nUBucket, nUBucketPos);
176 assert(vvNew[nUBucket][nUBucketPos] == -1);
179 infoOld.nRefCount = 1;
180 vvNew[nUBucket][nUBucketPos] = nIdEvict;
183 assert(vvTried[nKBucket][nKBucketPos] == -1);
185 vvTried[nKBucket][nKBucketPos] = nId;
223 int nB = (n + nRnd) % ADDRMAN_NEW_BUCKET_COUNT;
225 if (vvNew[nB][nBpos] == nId) {
239 MakeTried(info, nId);
252 if (addr == source) {
259 int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
260 if (addr.
nTime && (!pinfo->
nTime || pinfo->
nTime < addr.
nTime - nUpdateInterval - nTimePenalty))
280 for (
int n = 0; n < pinfo->
nRefCount; n++)
282 if (nFactor > 1 && (RandomInt(nFactor) != 0))
285 pinfo =
Create(addr, source, &nId);
293 if (vvNew[nUBucket][nUBucketPos] != nId) {
294 bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
296 CAddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
303 ClearNew(nUBucket, nUBucketPos);
305 vvNew[nUBucket][nUBucketPos] = nId;
342 if (newOnly && nNew == 0)
347 (nTried > 0 && (nNew == 0 || RandomInt(2) == 0))) {
349 double fChanceFactor = 1.0;
353 while (vvTried[nKBucket][nKBucketPos] == -1) {
357 int nId = vvTried[nKBucket][nKBucketPos];
358 assert(mapInfo.count(nId) == 1);
360 if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
362 fChanceFactor *= 1.2;
366 double fChanceFactor = 1.0;
370 while (vvNew[nUBucket][nUBucketPos] == -1) {
374 int nId = vvNew[nUBucket][nUBucketPos];
375 assert(mapInfo.count(nId) == 1);
377 if (RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
379 fChanceFactor *= 1.2;
385 int CAddrMan::Check_()
387 std::set<int> setTried;
388 std::map<int, int> mapNew;
390 if (vRandom.size() != nTried + nNew)
393 for (std::map<int, CAddrInfo>::iterator it = mapInfo.begin(); it != mapInfo.end(); it++) {
409 if (mapAddr[info] != n)
419 if (setTried.size() != nTried)
421 if (mapNew.size() != nNew)
426 if (vvTried[n][i] != -1) {
427 if (!setTried.count(vvTried[n][i]))
433 setTried.erase(vvTried[n][i]);
440 if (vvNew[n][i] != -1) {
441 if (!mapNew.count(vvNew[n][i]))
445 if (--mapNew[vvNew[n][i]] == 0)
446 mapNew.erase(vvNew[n][i]);
469 for (
unsigned int n = 0; n < vRandom.size(); n++) {
470 if (vAddr.size() >= nNodes)
473 int nRndPos = RandomInt(vRandom.size() - n) + n;
474 SwapRandom(n, nRndPos);
475 assert(mapInfo.count(vRandom[n]) == 1);
477 const CAddrInfo& ai = mapInfo[vRandom[n]];
478 if (!ai.IsTerrible())
498 int64_t nUpdateInterval = 20 * 60;
499 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.
int GetTriedBucket(const uint256 &nKey) const
Calculate in which "tried" bucket this entry belongs.
ServiceFlags
nServices flags
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
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
assert(len-trim+(2 *lenIndices)<=WIDTH)
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.
double GetChance(int64_t nNow=GetAdjustedTime()) const
Calculate the relative chance this entry should be given when selecting nodes to connect to...
bool fInTried
in tried set? (memory only)
Extended statistics about a CAddress.
#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.
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2)
Swap two elements in vRandom.
std::string ToString() const
#define ADDRMAN_BUCKET_SIZE
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr)
find an entry, creating it if necessary.
std::vector< unsigned char > GetGroup() const
#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".
uint8_t const size_t const size
#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.
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.
dev::WithExisting max(dev::WithExisting _a, dev::WithExisting _b)
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 ...
int GetNewBucket(const uint256 &nKey, const CNetAddr &src) const
Calculate in which "new" bucket this entry belongs, given a certain source.
#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
bool IsTerrible(int64_t nNow=GetAdjustedTime()) const
Determine whether the statistics about this entry are bad enough so that it can just be deleted...
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
std::vector< unsigned char > GetKey() const