10 #if defined(HAVE_CONFIG_H)
71 READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
131 #define ADDRMAN_TRIED_BUCKET_COUNT_LOG2 8
134 #define ADDRMAN_NEW_BUCKET_COUNT_LOG2 10
137 #define ADDRMAN_BUCKET_SIZE_LOG2 6
140 #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8
143 #define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 64
146 #define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 8
149 #define ADDRMAN_HORIZON_DAYS 30
152 #define ADDRMAN_RETRIES 3
155 #define ADDRMAN_MAX_FAILURES 10
158 #define ADDRMAN_MIN_FAIL_DAYS 7
161 #define ADDRMAN_REPLACEMENT_HOURS 4
164 #define ADDRMAN_TRIED_BUCKET_COUNT (1 << ADDRMAN_TRIED_BUCKET_COUNT_LOG2)
165 #define ADDRMAN_NEW_BUCKET_COUNT (1 << ADDRMAN_NEW_BUCKET_COUNT_LOG2)
166 #define ADDRMAN_BUCKET_SIZE (1 << ADDRMAN_BUCKET_SIZE_LOG2)
169 #define ADDRMAN_SET_TRIED_COLLISION_SIZE 10
172 static const int64_t ADDRMAN_TEST_WINDOW = 40*60;
320 static std::vector<bool>
DecodeAsmap(fs::path path);
362 template <
typename Stream>
375 static constexpr uint8_t lowest_compatible = Format::V3_BIP155;
384 std::map<int, int> mapUnkIds;
386 for (
const auto& entry : mapInfo) {
387 mapUnkIds[entry.first] = nIds;
390 assert(nIds != nNew);
396 for (
const auto& entry : mapInfo) {
399 assert(nIds != nTried);
407 if (vvNew[bucket][i] != -1)
412 if (vvNew[bucket][i] != -1) {
413 int nIndex = mapUnkIds[vvNew[bucket][i]];
427 template <
typename Stream>
435 s_ >> Using<CustomUintFormatter<1>>(
format);
437 int stream_version = s_.GetVersion();
438 if (
format >= Format::V3_BIP155) {
441 stream_version |= ADDRV2_FORMAT;
451 "Unsupported format of addrman database: %u. It is compatible with formats >=%u, "
452 "but the maximum supported by this version of %s is %u.",
461 if (
format >= Format::V1_DETERMINISTIC) {
462 nUBuckets ^= (1 << 30);
466 throw std::ios_base::failure(
"Corrupt CAddrMan serialization, nNew exceeds limit.");
470 throw std::ios_base::failure(
"Corrupt CAddrMan serialization, nTried exceeds limit.");
474 for (
int n = 0; n < nNew; n++) {
479 vRandom.push_back(n);
485 for (
int n = 0; n < nTried; n++) {
490 if (vvTried[nKBucket][nKBucketPos] == -1) {
493 vRandom.push_back(nIdCount);
494 mapInfo[nIdCount] = info;
495 mapAddr[info] = nIdCount;
496 vvTried[nKBucket][nKBucketPos] = nIdCount;
505 std::map<int, int> entryToBucket;
507 for (
int bucket = 0; bucket < nUBuckets; bucket++) {
510 for (
int n = 0; n < nSize; n++) {
513 if (nIndex >= 0 && nIndex < nNew) {
514 entryToBucket[nIndex] = bucket;
519 uint256 supplied_asmap_version;
523 uint256 serialized_asmap_version;
524 if (
format >= Format::V2_ASMAP) {
525 s >> serialized_asmap_version;
528 for (
int n = 0; n < nNew; n++) {
530 int bucket = entryToBucket[n];
535 vvNew[bucket][nUBucketPos] = n;
543 if (vvNew[bucket][nUBucketPos] == -1) {
544 vvNew[bucket][nUBucketPos] = n;
552 for (std::map<int, CAddrInfo>::const_iterator it = mapInfo.begin(); it != mapInfo.end();) {
553 if (it->second.fInTried ==
false && it->second.nRefCount == 0) {
554 std::map<int, CAddrInfo>::const_iterator itCopy = it++;
561 if (nLost + nLostUnk > 0) {
562 LogPrint(
BCLog::ADDRMAN,
"addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
571 std::vector<int>().swap(vRandom);
575 vvNew[bucket][entry] = -1;
580 vvTried[bucket][entry] = -1;
606 return vRandom.size();
616 if ((err = Check_()))
617 LogPrintf(
"ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
642 for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
643 nAdd +=
Add_(*it,
source, nTimePenalty) ? 1 : 0;
656 Good_(addr, test_before_evict, nTime);
665 Attempt_(addr, fCountFailure, nTime);
717 std::vector<CAddress> vAddr;
720 GetAddr_(vAddr, max_addresses, max_pct, network);
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS
in how many buckets for entries with new addresses a single address may occur
#define ADDRMAN_BUCKET_SIZE
#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.
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.
void GetAddr_(std::vector< CAddress > &vAddr, size_t max_addresses, size_t max_pct, Optional< Network > network) EXCLUSIVE_LOCKS_REQUIRED(cs)
Return all or many randomly selected addresses, optionally by network.
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)
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".
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.
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, Optional< Network > network)
Return all or many randomly selected addresses, optionally by network.
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.
#define LogPrint(category,...)
boost::optional< T > Optional
Substitute for C++17 std::optional.
ServiceFlags
nServices flags
#define READWRITEAS(type, obj)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
int64_t GetAdjustedTime()