6 #ifndef BITCOIN_ADDRMAN_H
7 #define BITCOIN_ADDRMAN_H
66 READWRITE(obj.source, obj.nLastSuccess, obj.nAttempts);
125 #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
206 std::map<int, CAddrInfo> mapInfo
GUARDED_BY(cs);
209 std::map<CNetAddr, int> mapAddr
GUARDED_BY(cs);
308 static std::vector<bool>
DecodeAsmap(fs::path path);
350 template <
typename Stream>
363 static constexpr uint8_t lowest_compatible = Format::V3_BIP155;
364 s << static_cast<uint8_t>(INCOMPATIBILITY_BASE + lowest_compatible);
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]];
409 if (m_asmap.size() != 0) {
415 template <
typename Stream>
423 s_ >> Using<CustomUintFormatter<1>>(
format);
425 int stream_version = s_.GetVersion();
426 if (format >= Format::V3_BIP155) {
437 if (lowest_compatible > FILE_FORMAT) {
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.",
441 format, lowest_compatible,
PACKAGE_NAME, static_cast<uint8_t>(FILE_FORMAT)));
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++) {
477 int nKBucketPos = info.GetBucketPosition(nKey,
false, nKBucket);
478 if (vvTried[nKBucket][nKBucketPos] == -1) {
479 info.nRandomPos = vRandom.size();
480 info.fInTried =
true;
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;
508 if (m_asmap.size() != 0) {
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);
560 nKey = insecure_rand.
rand256();
563 vvNew[bucket][entry] = -1;
568 vvTried[bucket][entry] = -1;
594 return vRandom.size();
605 LogPrintf(
"ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
616 fRet |=
Add_(addr, source, nTimePenalty);
625 bool Add(
const std::vector<CAddress> &vAddr,
const CNetAddr& source, int64_t nTimePenalty = 0)
630 for (std::vector<CAddress>::const_iterator
it = vAddr.begin();
it != vAddr.end();
it++)
631 nAdd +=
Add_(*
it, source, nTimePenalty) ? 1 : 0;
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);
726 #endif // BITCOIN_ADDRMAN_H
int nRefCount
reference count in new sets (memory only)
for files including asmap version
friend class CAddrManTest
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...
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 GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
static constexpr uint8_t INCOMPATIBILITY_BASE
The initial value of a field that is incremented every time an incompatible format change is made (su...
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
find an entry, creating it if necessary.
static void LogPrintf(const char *fmt, const Args &...args)
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs)
Update an entry's service bits.
std::string ToStringIPPort() const
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.
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".
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
uint256 rand256() noexcept
generate a random uint256.
same as V2_ASMAP plus addresses are in BIP155 format
static const int64_t ADDRMAN_TEST_WINDOW
the maximum time we'll spend trying to resolve a tried table collision, in seconds ...
bool Add_(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty) EXCLUSIVE_LOCKS_REQUIRED(cs)
Add an entry to the "new" table.
int GetNewBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "new" bucket this entry belongs, using its default source.
std::set< int > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries. Test-before-evict disciplin...
int nIdCount GUARDED_BY(cs)
last used nId
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.
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)
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)
Stochastical (IP) address manager.
static constexpr Format FILE_FORMAT
The maximum format this software knows it can unserialize.
static constexpr int ADDRV2_FORMAT
A flag that is ORed into the protocol version to designate that addresses should be serialized in (un...
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.
size_t size() const
Return the number of (unique) addresses in all tables.
Extended statistics about a CAddress.
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.
historic format, before commit e6b343d88
A combination of a network address (CNetAddr) and a (TCP) port.
void Check()
Consistency check.
void Unserialize(Stream &s_)
A CService with information about it as peer.
#define ADDRMAN_BUCKET_SIZE
Format
Serialization versions.
int GetTriedBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "tried" bucket this entry belongs.
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 Serialize(Stream &s_) const
Serialized format.
#define EXCLUSIVE_LOCKS_REQUIRED(...)
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...
SERIALIZE_METHODS(CAddrInfo, obj)
void Connected_(const CService &addr, int64_t nTime) EXCLUSIVE_LOCKS_REQUIRED(cs)
Mark an entry as currently-connected-to.
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::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct)
Return a bunch of addresses, selected at random.
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...
static std::vector< bool > DecodeAsmap(fs::path path)
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.
std::string ToString() const
void SetServices(const CService &addr, ServiceFlags nServices)
uint256 nKey
secret key to randomize bucket select with
void GetAddr_(std::vector< CAddress > &vAddr, size_t max_addresses, size_t max_pct) EXCLUSIVE_LOCKS_REQUIRED(cs)
Select several addresses at once.
void Connected(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as currently-connected-to.
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...
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
CAddrInfo * Find(const CNetAddr &addr, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Find an entry.