6 #ifndef BITCOIN_ADDRMAN_H
7 #define BITCOIN_ADDRMAN_H
66 READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
126 #define ADDRMAN_TRIED_BUCKET_COUNT_LOG2 8
129 #define ADDRMAN_NEW_BUCKET_COUNT_LOG2 10
132 #define ADDRMAN_BUCKET_SIZE_LOG2 6
135 #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8
138 #define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 64
141 #define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 8
144 #define ADDRMAN_HORIZON_DAYS 30
147 #define ADDRMAN_RETRIES 3
150 #define ADDRMAN_MAX_FAILURES 10
153 #define ADDRMAN_MIN_FAIL_DAYS 7
156 #define ADDRMAN_REPLACEMENT_HOURS 4
159 #define ADDRMAN_TRIED_BUCKET_COUNT (1 << ADDRMAN_TRIED_BUCKET_COUNT_LOG2)
160 #define ADDRMAN_NEW_BUCKET_COUNT (1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2)
161 #define ADDRMAN_BUCKET_SIZE (1 << ADDRMAN_BUCKET_SIZE_LOG2)
164 #define ADDRMAN_SET_TRIED_COLLISION_SIZE 10
308 static std::vector<bool>
DecodeAsmap(fs::path path);
350 template <
typename Stream>
363 static constexpr uint8_t lowest_compatible = Format::V3_BIP155;
372 std::map<int, int> mapUnkIds;
374 for (
const auto& entry : mapInfo) {
375 mapUnkIds[entry.first] = nIds;
378 assert(nIds != nNew);
384 for (
const auto& entry : mapInfo) {
387 assert(nIds != nTried);
395 if (vvNew[bucket][i] != -1)
400 if (vvNew[bucket][i] != -1) {
401 int nIndex = mapUnkIds[vvNew[bucket][i]];
415 template <
typename Stream>
423 s_ >> Using<CustomUintFormatter<1>>(
format);
425 int stream_version = s_.GetVersion();
426 if (
format >= Format::V3_BIP155) {
439 "Unsupported format of addrman database: %u. It is compatible with formats >=%u, "
440 "but the maximum supported by this version of %s is %u.",
449 if (
format >= Format::V1_DETERMINISTIC) {
450 nUBuckets ^= (1 << 30);
454 throw std::ios_base::failure(
"Corrupt CAddrMan serialization, nNew exceeds limit.");
458 throw std::ios_base::failure(
"Corrupt CAddrMan serialization, nTried exceeds limit.");
462 for (
int n = 0; n < nNew; n++) {
467 vRandom.push_back(n);
473 for (
int n = 0; n < nTried; n++) {
478 if (vvTried[nKBucket][nKBucketPos] == -1) {
481 vRandom.push_back(nIdCount);
482 mapInfo[nIdCount] = info;
483 mapAddr[info] = nIdCount;
484 vvTried[nKBucket][nKBucketPos] = nIdCount;
493 std::map<int, int> entryToBucket;
495 for (
int bucket = 0; bucket < nUBuckets; bucket++) {
498 for (
int n = 0; n < nSize; n++) {
501 if (nIndex >= 0 && nIndex < nNew) {
502 entryToBucket[nIndex] = bucket;
507 uint256 supplied_asmap_version;
511 uint256 serialized_asmap_version;
512 if (
format >= Format::V2_ASMAP) {
513 s >> serialized_asmap_version;
516 for (
int n = 0; n < nNew; n++) {
518 int bucket = entryToBucket[n];
523 vvNew[bucket][nUBucketPos] = n;
531 if (vvNew[bucket][nUBucketPos] == -1) {
532 vvNew[bucket][nUBucketPos] = n;
540 for (std::map<int, CAddrInfo>::const_iterator
it = mapInfo.begin();
it != mapInfo.end(); ) {
541 if (
it->second.fInTried ==
false &&
it->second.nRefCount == 0) {
542 std::map<int, CAddrInfo>::const_iterator itCopy =
it++;
549 if (nLost + nLostUnk > 0) {
550 LogPrint(
BCLog::ADDRMAN,
"addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
559 std::vector<int>().swap(vRandom);
563 vvNew[bucket][entry] = -1;
568 vvTried[bucket][entry] = -1;
594 return vRandom.size();
605 LogPrintf(
"ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
630 for (std::vector<CAddress>::const_iterator
it = vAddr.begin();
it != vAddr.end();
it++)
644 Good_(addr, test_before_evict, nTime);
653 Attempt_(addr, fCountFailure, nTime);
695 std::vector<CAddress>
GetAddr(
size_t max_addresses,
size_t max_pct)
698 std::vector<CAddress> vAddr;
701 GetAddr_(vAddr, max_addresses, max_pct);
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS
in how many buckets for entries with new addresses a single address may occur
#define ADDRMAN_BUCKET_SIZE
static const int64_t ADDRMAN_TEST_WINDOW
the maximum time we'll spend trying to resolve a tried table collision, in seconds
#define ADDRMAN_NEW_BUCKET_COUNT
#define ADDRMAN_TRIED_BUCKET_COUNT
Convenience.
Extended statistics about a CAddress.
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
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
int64_t nLastSuccess
last successful connection by us
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
int64_t nLastCountAttempt
last counted attempt (memory only)
int64_t nLastTry
last try whatsoever by us (memory only)
bool IsTerrible(int64_t nNow=GetAdjustedTime()) const
Determine whether the statistics about this entry are bad enough so that it can just be deleted.
int nRandomPos
position in vRandom
bool fInTried
in tried set? (memory only)
int GetNewBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "new" bucket this entry belongs, using its default source.
SERIALIZE_METHODS(CAddrInfo, obj)
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.
int nRefCount
reference count in new sets (memory only)
CNetAddr source
where knowledge about this address first came from
double GetChance(int64_t nNow=GetAdjustedTime()) const
Calculate the relative chance this entry should be given when selecting nodes to connect to.
Stochastical (IP) address manager.
bool Add(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty=0)
Add a single address.
int64_t nLastGood GUARDED_BY(cs)
last time Good was called (memory only)
static constexpr uint8_t INCOMPATIBILITY_BASE
The initial value of a field that is incremented every time an incompatible format change is made (su...
void Unserialize(Stream &s_)
void Serialize(Stream &s_) const
Serialized format.
void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Delete an entry. It must not be in tried, and have refcount 0.
std::vector< int > vRandom GUARDED_BY(cs)
randomly-ordered vector of all nIds
void Check()
Consistency check.
bool Add_(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs)
Add an entry to the "new" table.
Format
Serialization versions.
@ V1_DETERMINISTIC
for pre-asmap files
@ V0_HISTORICAL
historic format, before commit e6b343d88
@ V3_BIP155
same as V2_ASMAP plus addresses are in BIP155 format
@ V2_ASMAP
for files including asmap version
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs)
list of "tried" buckets
FastRandomContext insecure_rand
Source of random numbers for randomization in inner loops.
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
find an entry, creating it if necessary.
size_t size() const
Return the number of (unique) addresses in all tables.
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct)
Return a bunch of addresses, selected at random.
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs)
list of "new" buckets
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime=GetAdjustedTime())
Mark an entry as connection attempted to.
int nIdCount GUARDED_BY(cs)
last used nId
CAddrInfo SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs)
Return a random to-be-evicted tried table address.
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) EXCLUSIVE_LOCKS_REQUIRED(cs)
Swap two elements in vRandom.
std::set< int > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries. Test-before-evict disciplin...
CAddrInfo Select(bool newOnly=false)
Choose an address to connect to.
RecursiveMutex cs
critical section to protect the inner data structures
void ResolveCollisions()
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
CAddrInfo SelectTriedCollision()
Randomly select an address in tried that another address is attempting to evict.
CAddrInfo * Find(const CNetAddr &addr, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Find an entry.
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.
void Connected(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as currently-connected-to.
std::map< CNetAddr, int > mapAddr GUARDED_BY(cs)
find an nId based on its network address
int nNew GUARDED_BY(cs)
number of (unique) "new" entries
void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry as attempted to connect.
int nTried GUARDED_BY(cs)
friend class CAddrManTest
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Add multiple addresses.
static constexpr Format FILE_FORMAT
The maximum format this software knows it can unserialize.
std::map< int, CAddrInfo > mapInfo GUARDED_BY(cs)
table with information about all nIds
void SetServices(const CService &addr, ServiceFlags nServices)
std::vector< bool > m_asmap
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".
void GetAddr_(std::vector< CAddress > &vAddr, size_t max_addresses, size_t max_pct) EXCLUSIVE_LOCKS_REQUIRED(cs)
Select several addresses at once.
static std::vector< bool > DecodeAsmap(fs::path path)
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) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update an entry's service bits.
uint256 nKey
secret key to randomize bucket select with
void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry as currently-connected-to.
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.
void MakeTried(CAddrInfo &info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Move an entry from the "new" table(s) to the "tried" table.
void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs)
See if any to-be-evicted tried table entries have been tested and if so resolve the collisions.
A CService with information about it as peer.
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringIPPort() const
uint256 rand256() noexcept
generate a random uint256.
uint256 SerializeHash(const T &obj, int nType=SER_GETHASH, int nVersion=PROTOCOL_VERSION)
Compute the 256-bit hash of an object's serialization.
static void LogPrintf(const char *fmt, const Args &... args)
#define LogPrint(category,...)
std::deque< CInv >::iterator it
static constexpr int ADDRV2_FORMAT
A flag that is ORed into the protocol version to designate that addresses should be serialized in (un...
ServiceFlags
nServices flags
#define READWRITEAS(type, obj)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t GetAdjustedTime()