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)
63 fChance *= pow(0.66, std::min(
nAttempts, 8));
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);
117 assert(!info.fInTried);
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) {
148 vvNew[bucket][pos] = -1;
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);
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;
225 if (vvNew[nB][nBpos] == nId) {
241 if (test_before_evict && (vvTried[tried_bucket][tried_bucket_pos] != -1)) {
271 int64_t nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
272 if (addr.
nTime && (!pinfo->
nTime || pinfo->
nTime < addr.
nTime - nUpdateInterval - nTimePenalty))
273 pinfo->
nTime = std::max((int64_t)0, addr.
nTime - nTimePenalty);
292 for (
int n = 0; n < pinfo->
nRefCount; n++)
294 if (nFactor > 1 && (
RandomInt(nFactor) != 0))
298 pinfo->
nTime = std::max((int64_t)0, (int64_t)pinfo->
nTime - nTimePenalty);
305 if (vvNew[nUBucket][nUBucketPos] != nId) {
306 bool fInsert = vvNew[nUBucket][nUBucketPos] == -1;
308 CAddrInfo& infoExisting = mapInfo[vvNew[nUBucket][nUBucketPos]];
317 vvNew[nUBucket][nUBucketPos] = nId;
354 if (newOnly && nNew == 0)
359 (nTried > 0 && (nNew == 0 ||
RandomInt(2) == 0))) {
361 double fChanceFactor = 1.0;
365 while (vvTried[nKBucket][nKBucketPos] == -1) {
369 int nId = vvTried[nKBucket][nKBucketPos];
370 assert(mapInfo.count(nId) == 1);
372 if (
RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
374 fChanceFactor *= 1.2;
378 double fChanceFactor = 1.0;
382 while (vvNew[nUBucket][nUBucketPos] == -1) {
386 int nId = vvNew[nUBucket][nUBucketPos];
387 assert(mapInfo.count(nId) == 1);
389 if (
RandomInt(1 << 30) < fChanceFactor * info.GetChance() * (1 << 30))
391 fChanceFactor *= 1.2;
397 int CAddrMan::Check_()
399 std::set<int> setTried;
400 std::map<int, int> mapNew;
402 if (vRandom.size() != (size_t)(nTried + nNew))
405 for (
const auto& entry : mapInfo) {
421 if (mapAddr[info] != n)
431 if (setTried.size() != (size_t)nTried)
433 if (mapNew.size() != (size_t)nNew)
438 if (vvTried[n][i] != -1) {
439 if (!setTried.count(vvTried[n][i]))
441 if (mapInfo[vvTried[n][i]].GetTriedBucket(
nKey) != n)
443 if (mapInfo[vvTried[n][i]].GetBucketPosition(
nKey,
false, n) != i)
445 setTried.erase(vvTried[n][i]);
452 if (vvNew[n][i] != -1) {
453 if (!mapNew.count(vvNew[n][i]))
455 if (mapInfo[vvNew[n][i]].GetBucketPosition(
nKey,
true, n) != i)
457 if (--mapNew[vvNew[n][i]] == 0)
458 mapNew.erase(vvNew[n][i]);
481 for (
unsigned int n = 0; n < vRandom.size(); n++) {
482 if (vAddr.size() >= nNodes)
485 int nRndPos =
RandomInt(vRandom.size() - n) + n;
487 assert(mapInfo.count(vRandom[n]) == 1);
489 const CAddrInfo& ai = mapInfo[vRandom[n]];
490 if (!ai.IsTerrible())
510 int64_t nUpdateInterval = 20 * 60;
511 if (nTime - info.
nTime > nUpdateInterval)
542 bool erase_collision =
false;
545 if (mapInfo.count(id_new) != 1) {
546 erase_collision =
true;
554 erase_collision =
true;
555 }
else if (vvTried[tried_bucket][tried_bucket_pos] != -1) {
558 int id_old = vvTried[tried_bucket][tried_bucket_pos];
563 erase_collision =
true;
572 erase_collision =
true;
577 erase_collision =
true;
581 if (erase_collision) {
600 if (mapInfo.count(id_new) != 1) {
611 int id_old = vvTried[tried_bucket][tried_bucket_pos];
613 return mapInfo[id_old];
int nRefCount
reference count in new sets (memory only)
uint64_t randbits(int bits)
Generate a random (bits)-bit integer.
ServiceFlags
nServices flags
void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs)
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions...
#define ADDRMAN_SET_TRIED_COLLISION_SIZE
the maximum number of tried addr collisions to store
#define ADDRMAN_TRIED_BUCKET_COUNT_LOG2
Stochastic address manager.
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
find an entry, creating it if necessary.
#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) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update an entry's service bits.
void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Delete an entry. It must not be in tried, and have refcount 0.
void Good_(const CService &addr, bool test_before_evict, int64_t time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry "good", possibly moving it from "new" to "tried".
#define ADDRMAN_MIN_FAIL_DAYS
... in at least this many days
#define ADDRMAN_REPLACEMENT_HOURS
how recent a successful connection should be before we allow an address to be evicted from tried ...
void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry as attempted to connect.
int nAttempts
connection attempts since last successful attempt
#define ADDRMAN_NEW_BUCKET_COUNT_LOG2
total number of buckets for new addresses
bool Add_(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs)
Add an entry to the "new" table.
std::set< int > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries. Test-before-evict disciplin...
virtual int RandomInt(int nMax)
Wraps GetRandInt to allow tests to override RandomInt and make it determinismistic.
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) EXCLUSIVE_LOCKS_REQUIRED(cs)
Swap two elements in vRandom.
int nRandomPos
position in vRandom
CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs)
Return a random to-be-evicted tried table address.
#define ADDRMAN_TRIED_BUCKET_COUNT
Convenience.
bool fInTried
in tried set? (memory only)
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
FastRandomContext insecure_rand
Source of random numbers for randomization in inner loops.
void MakeTried(CAddrInfo &info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
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
#define ADDRMAN_BUCKET_SIZE
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) EXCLUSIVE_LOCKS_REQUIRED(cs)
Clear a position in a "new" table. This is the only place where entries are actually deleted...
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
size_t size() const
Return the number of (unique) addresses in all tables.
CAddrInfo Select_(bool newOnly) EXCLUSIVE_LOCKS_REQUIRED(cs)
Select an address to connect to, if newOnly is set to true, only the new table is selected from...
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry as currently-connected-to.
#define ADDRMAN_NEW_BUCKET_COUNT
int64_t GetAdjustedTime()
double GetChance(int64_t nNow=GetAdjustedTime()) const
Calculate the relative chance this entry should be given when selecting nodes to connect to...
int64_t nLastCountAttempt
last counted attempt (memory only)
void GetAddr_(std::vector< CAddress > &vAddr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Select several addresses at once.
A writer stream (for serialization) that computes a 256-bit SHA-3-256 hash.
std::string ToString() const
uint256 nKey
secret key to randomize bucket select with
#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
#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
CAddrInfo * Find(const CNetAddr &addr, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Find an entry.