6 #ifndef BITCOIN_ADDRMAN_H
7 #define BITCOIN_ADDRMAN_H
60 template <
typename Stream,
typename Operation>
139 #define ADDRMAN_TRIED_BUCKET_COUNT 256
142 #define ADDRMAN_NEW_BUCKET_COUNT 1024
145 #define ADDRMAN_BUCKET_SIZE 64
148 #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8
151 #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
169 #define ADDRMAN_GETADDR_MAX_PCT 23
172 #define ADDRMAN_GETADDR_MAX 2500
225 void SwapRandom(
unsigned int nRandomPos1,
unsigned int nRandomPos2);
234 void ClearNew(
int nUBucket,
int nUBucketPos);
257 void GetAddr_(std::vector<CAddress> &vAddr);
295 template<
typename Stream>
300 unsigned char nVersion = 1;
302 s << ((
unsigned char)32);
309 std::map<int, int> mapUnkIds;
311 for (std::map<int, CAddrInfo>::const_iterator it =
mapInfo.begin(); it !=
mapInfo.end(); it++) {
312 mapUnkIds[(*it).first] = nIds;
315 assert(nIds !=
nNew);
321 for (std::map<int, CAddrInfo>::const_iterator it =
mapInfo.begin(); it !=
mapInfo.end(); it++) {
332 if (
vvNew[bucket][i] != -1)
337 if (
vvNew[bucket][i] != -1) {
338 int nIndex = mapUnkIds[
vvNew[bucket][i]];
345 template<
typename Stream>
352 unsigned char nVersion;
354 unsigned char nKeySize;
356 if (nKeySize != 32)
throw std::ios_base::failure(
"Incorrect keysize in addrman deserialization");
363 nUBuckets ^= (1 << 30);
367 throw std::ios_base::failure(
"Corrupt CAddrMan serialization, nNew exceeds limit.");
371 throw std::ios_base::failure(
"Corrupt CAddrMan serialization, nTried exceeds limit.");
375 for (
int n = 0; n <
nNew; n++) {
386 if (
vvNew[nUBucket][nUBucketPos] == -1) {
387 vvNew[nUBucket][nUBucketPos] = n;
396 for (
int n = 0; n <
nTried; n++) {
401 if (
vvTried[nKBucket][nKBucketPos] == -1) {
416 for (
int bucket = 0; bucket < nUBuckets; bucket++) {
419 for (
int n = 0; n < nSize; n++) {
422 if (nIndex >= 0 && nIndex <
nNew) {
427 vvNew[bucket][nUBucketPos] = nIndex;
435 for (std::map<int, CAddrInfo>::const_iterator it =
mapInfo.begin(); it !=
mapInfo.end(); ) {
436 if (it->second.fInTried ==
false && it->second.nRefCount == 0) {
437 std::map<int, CAddrInfo>::const_iterator itCopy = it++;
444 if (nLost + nLostUnk > 0) {
445 LogPrint(
"addrman",
"addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
453 std::vector<int>().swap(
vRandom);
457 vvNew[bucket][entry] = -1;
497 LogPrintf(
"ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
521 for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
522 nAdd +=
Add_(*it,
source, nTimePenalty) ? 1 : 0;
543 Attempt_(addr, fCountFailure, nTime);
566 std::vector<CAddress> vAddr;
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS
in how many buckets for entries with new addresses a single address may occur
#define ADDRMAN_BUCKET_SIZE
maximum allowed number of entries in buckets for new and tried addresses
#define ADDRMAN_NEW_BUCKET_COUNT
total number of buckets for new addresses
#define ADDRMAN_TRIED_BUCKET_COUNT
Stochastic address manager.
Extended statistics about a CAddress.
int GetNewBucket(const uint256 &nKey) const
Calculate in which "new" bucket this entry belongs, using its default source.
int GetTriedBucket(const uint256 &nKey) const
Calculate in which "tried" bucket this entry belongs.
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
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)
void SerializationOp(Stream &s, Operation ser_action)
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 nRefCount
reference count in new sets (memory only)
CNetAddr source
where knowledge about this address first came from
int GetNewBucket(const uint256 &nKey, const CNetAddr &src) const
Calculate in which "new" bucket this entry belongs, given a certain source.
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.
int64_t nLastGood
last time Good was called (memory only)
bool Add(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty=0)
Add a single address.
void Check()
Consistency check.
std::map< int, CAddrInfo > mapInfo
table with information about all nIds
void Connected_(const CService &addr, int64_t nTime)
Mark an entry as currently-connected-to.
FastRandomContext insecure_rand
Source of random numbers for randomization in inner loops.
size_t size() const
Return the number of (unique) addresses in all tables.
CAddrInfo Select_(bool newOnly)
Select an address to connect to, if newOnly is set to true, only the new table is selected from.
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2)
Swap two elements in vRandom.
void Good_(const CService &addr, int64_t nTime)
Mark an entry "good", possibly moving it from "new" to "tried".
void Serialize(Stream &s) const
serialized format:
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE]
list of "tried" buckets
void Attempt(const CService &addr, bool fCountFailure, int64_t nTime=GetAdjustedTime())
Mark an entry as connection attempted to.
int nNew
number of (unique) "new" entries
virtual int RandomInt(int nMax)
Wraps GetRandInt to allow tests to override RandomInt and make it determinismistic.
std::map< CNetAddr, int > mapAddr
find an nId based on its network address
CAddrInfo Select(bool newOnly=false)
Choose an address to connect to.
std::vector< CAddress > GetAddr()
Return a bunch of addresses, selected at random.
int nIdCount
last used nId
void Connected(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as currently-connected-to.
void Unserialize(Stream &s)
void MakeTried(CAddrInfo &info, int nId)
Move an entry from the "new" table(s) to the "tried" table.
void Good(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as accessible.
void Attempt_(const CService &addr, bool fCountFailure, int64_t nTime)
Mark an entry as attempted to connect.
bool Add_(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty)
Add an entry to the "new" table.
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Add multiple addresses.
CCriticalSection cs
critical section to protect the inner data structures
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=NULL)
find an entry, creating it if necessary.
void ClearNew(int nUBucket, int nUBucketPos)
Clear a position in a "new" table. This is the only place where entries are actually deleted.
void SetServices(const CService &addr, ServiceFlags nServices)
CAddrInfo * Find(const CNetAddr &addr, int *pnId=NULL)
Find an entry.
uint256 nKey
secret key to randomize bucket select with
void Delete(int nId)
Delete an entry. It must not be in tried, and have refcount 0.
std::vector< int > vRandom
randomly-ordered vector of all nIds
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE]
list of "new" buckets
void SetServices_(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
void GetAddr_(std::vector< CAddress > &vAddr)
Select several addresses at once.
A CService with information about it as peer.
Wrapped boost mutex: supports recursive locking, but no waiting TODO: We should move away from using ...
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
A combination of a network address (CNetAddr) and a (TCP) port.
std::string ToStringIPPort() const
ServiceFlags
nServices flags
int64_t GetAdjustedTime()
#define LogPrint(category,...)