6 #ifndef BITCOIN_ADDRMAN_H 7 #define BITCOIN_ADDRMAN_H 61 READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
65 :
CAddress(addrIn), source(addrSource) {}
71 const std::vector<bool> &asmap)
const;
76 const std::vector<bool> &asmap)
const;
81 const std::vector<bool> &asmap)
const {
135 #define ADDRMAN_TRIED_BUCKET_COUNT_LOG2 8 139 #define ADDRMAN_NEW_BUCKET_COUNT_LOG2 10 142 #define ADDRMAN_BUCKET_SIZE_LOG2 6 146 #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8 150 #define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 64 154 #define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 8 157 #define ADDRMAN_HORIZON_DAYS 30 160 #define ADDRMAN_RETRIES 3 163 #define ADDRMAN_MAX_FAILURES 10 166 #define ADDRMAN_MIN_FAIL_DAYS 7 170 #define ADDRMAN_REPLACEMENT_SECONDS (4 * 60 * 60) 173 #define ADDRMAN_GETADDR_MAX_PCT 23 176 #define ADDRMAN_GETADDR_MAX 2500 179 #define ADDRMAN_TRIED_BUCKET_COUNT (1 << ADDRMAN_TRIED_BUCKET_COUNT_LOG2) 180 #define ADDRMAN_NEW_BUCKET_COUNT (1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2) 181 #define ADDRMAN_BUCKET_SIZE (1 << ADDRMAN_BUCKET_SIZE_LOG2) 184 #define ADDRMAN_SET_TRIED_COLLISION_SIZE 10 194 friend class CAddrManTest;
205 std::map<int, CAddrInfo> mapInfo
GUARDED_BY(cs);
208 std::map<CNetAddr, int> mapAddr
GUARDED_BY(cs);
249 void SwapRandom(
unsigned int nRandomPos1,
unsigned int nRandomPos2)
263 void Good_(const
CService &addr,
bool test_before_evict, int64_t time)
271 void Attempt_(const
CService &addr,
bool fCountFailure, int64_t
nTime)
319 static std::vector<bool> DecodeAsmap(fs::path path);
353 template <
typename Stream>
void Serialize(Stream &s)
const {
356 uint8_t nVersion = 2;
365 std::map<int, int> mapUnkIds;
367 for (
const auto &entry : mapInfo) {
368 mapUnkIds[entry.first] = nIds;
372 assert(nIds != nNew);
378 for (
const auto &entry : mapInfo) {
382 assert(nIds != nTried);
390 if (vvNew[bucket][i] != -1) nSize++;
394 if (vvNew[bucket][i] != -1) {
395 int nIndex = mapUnkIds[vvNew[bucket][i]];
403 if (m_asmap.size() != 0) {
417 if (nKeySize != 32) {
418 throw std::ios_base::failure(
419 "Incorrect keysize in addrman deserialization");
428 nUBuckets ^= (1 << 30);
432 throw std::ios_base::failure(
433 "Corrupt CAddrMan serialization, nNew exceeds limit.");
437 throw std::ios_base::failure(
438 "Corrupt CAddrMan serialization, nTried exceeds limit.");
442 for (
int n = 0; n < nNew; n++) {
447 vRandom.push_back(n);
453 for (
int n = 0; n < nTried; n++) {
457 int nKBucketPos = info.GetBucketPosition(nKey,
false, nKBucket);
458 if (vvTried[nKBucket][nKBucketPos] == -1) {
459 info.nRandomPos = vRandom.size();
460 info.fInTried =
true;
461 vRandom.push_back(nIdCount);
462 mapInfo[nIdCount] = info;
463 mapAddr[info] = nIdCount;
464 vvTried[nKBucket][nKBucketPos] = nIdCount;
475 std::map<int, int> entryToBucket;
477 for (
int bucket = 0; bucket < nUBuckets; bucket++) {
480 for (
int n = 0; n < nSize; n++) {
483 if (nIndex >= 0 && nIndex < nNew) {
484 entryToBucket[nIndex] = bucket;
489 uint256 supplied_asmap_version;
490 if (m_asmap.size() != 0) {
493 uint256 serialized_asmap_version;
495 s >> serialized_asmap_version;
498 for (
int n = 0; n < nNew; n++) {
500 int bucket = entryToBucket[n];
503 vvNew[bucket][nUBucketPos] == -1 &&
505 serialized_asmap_version == supplied_asmap_version) {
508 vvNew[bucket][nUBucketPos] = n;
515 "Bucketing method was updated, re-bucketing addrman " 516 "entries from disk\n");
519 if (vvNew[bucket][nUBucketPos] == -1) {
520 vvNew[bucket][nUBucketPos] = n;
528 for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin();
529 it != mapInfo.end();) {
530 if (it->second.fInTried ==
false && it->second.nRefCount == 0) {
531 std::map<int, CAddrInfo>::const_iterator itCopy = it++;
532 Delete(itCopy->first);
538 if (nLost + nLostUnk > 0) {
540 "addrman lost %i new and %i tried addresses due to " 550 std::vector<int>().swap(vRandom);
551 nKey = insecure_rand.
rand256();
554 vvNew[bucket][entry] = -1;
559 vvTried[bucket][entry] = -1;
580 return vRandom.size();
589 if ((err = Check_())) {
590 LogPrintf(
"ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
598 int64_t nTimePenalty = 0) {
602 fRet |= Add_(addr, source, nTimePenalty);
612 bool Add(
const std::vector<CAddress> &vAddr,
const CNetAddr &source,
613 int64_t nTimePenalty = 0) {
618 nAdd += Add_(a, source, nTimePenalty) ? 1 : 0;
623 "Added %i addresses from %s: %i tried, %i new\n", nAdd,
634 Good_(addr, test_before_evict,
nTime);
643 Attempt_(addr, fCountFailure,
nTime);
652 ResolveCollisions_();
663 ret = SelectTriedCollision_();
677 addrRet = Select_(newOnly);
686 std::vector<CAddress> vAddr;
699 Connected_(addr,
nTime);
706 SetServices_(addr, nServices);
711 #endif // BITCOIN_ADDRMAN_H int nRefCount
reference count in new sets (memory only)
ServiceFlags
nServices flags.
CAddrInfo Select(bool newOnly=false)
Choose an address to connect to.
#define LogPrint(category,...)
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime=GetAdjustedTime())
Mark an entry as connection attempted to.
int GetTriedBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "tried" bucket this entry belongs.
int nAttempts
connection attempts since last successful attempt
uint256 rand256() noexcept
generate a random uint256.
static void LogPrintf(const char *fmt, const Args &... args)
static const int64_t ADDRMAN_TEST_WINDOW
the maximum time we'll spend trying to resolve a tried table collision, in seconds (40 minutes) ...
std::set< int > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries.
std::string ToString() const
int nRandomPos
position in vRandom
bool Add(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty=0)
Add a single address.
#define ADDRMAN_TRIED_BUCKET_COUNT
Convenience.
#define READWRITEAS(type, obj)
bool fInTried
in tried set? (memory only)
Stochastical (IP) address manager.
RecursiveMutex cs
critical section to protect the inner data structures
uint256 SerializeHash(const T &obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Compute the 256-bit hash of an object's serialization.
std::vector< CAddress > GetAddr()
Return a bunch of addresses, selected at random.
Extended statistics about a CAddress.
FastRandomContext insecure_rand
Source of random numbers for randomization in inner loops.
void Unserialize(Stream &s)
A combination of a network address (CNetAddr) and a (TCP) port.
void Check()
Consistency check.
int GetNewBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "new" bucket this entry belongs, using its default source.
A CService with information about it as peer.
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.
#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...
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
size_t size() const
Return the number of (unique) addresses in all tables.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
SERIALIZE_METHODS(CAddrInfo, obj)
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
#define ADDRMAN_NEW_BUCKET_COUNT
int64_t GetAdjustedTime()
CAddrInfo SelectTriedCollision()
Randomly select an address in tried that another address is attempting to evict.
std::string ToStringIPPort() const
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 ResolveCollisions()
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions...
std::vector< bool > m_asmap
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Add multiple addresses.
void Good(const CService &addr, bool test_before_evict=true, int64_t nTime=GetAdjustedTime())
Mark an entry as accessible.
void SetServices(const CService &addr, ServiceFlags nServices)
uint256 nKey
secret key to randomize bucket select with
void Serialize(Stream &s) const
serialized format:
void Connected(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as currently-connected-to.
int64_t nLastSuccess
last successful connection by us
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