5 #ifndef BITCOIN_ADDRMAN_H 6 #define BITCOIN_ADDRMAN_H 56 template <
typename Stream,
typename Operation>
57 inline void SerializationOp(Stream& s, Operation ser_action,
int nType,
int nVersion) {
133 #define ADDRMAN_TRIED_BUCKET_COUNT 256 137 #define ADDRMAN_NEW_BUCKET_COUNT 1024 140 #define ADDRMAN_BUCKET_SIZE 64 143 #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 8 146 #define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 64 149 #define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 8 152 #define ADDRMAN_HORIZON_DAYS 30 155 #define ADDRMAN_RETRIES 3 158 #define ADDRMAN_MAX_FAILURES 10 161 #define ADDRMAN_MIN_FAIL_DAYS 7 164 #define ADDRMAN_GETADDR_MAX_PCT 23 167 #define ADDRMAN_GETADDR_MAX 2500 214 void SwapRandom(
unsigned int nRandomPos1,
unsigned int nRandomPos2);
223 void ClearNew(
int nUBucket,
int nUBucketPos);
246 void GetAddr_(std::vector<CAddress> &vAddr);
284 template<
typename Stream>
285 void Serialize(Stream &s,
int nType,
int nVersionDummy)
const 289 unsigned char nVersion = 1;
291 s << ((
unsigned char)32);
298 std::map<int, int> mapUnkIds;
300 for (std::map<int, CAddrInfo>::const_iterator it =
mapInfo.begin(); it !=
mapInfo.end(); it++) {
301 mapUnkIds[(*it).first] = nIds;
304 assert(nIds !=
nNew);
310 for (std::map<int, CAddrInfo>::const_iterator it =
mapInfo.begin(); it !=
mapInfo.end(); it++) {
321 if (
vvNew[bucket][i] != -1)
326 if (
vvNew[bucket][i] != -1) {
327 int nIndex = mapUnkIds[
vvNew[bucket][i]];
334 template<
typename Stream>
341 unsigned char nVersion;
343 unsigned char nKeySize;
345 if (nKeySize != 32)
throw std::ios_base::failure(
"Incorrect keysize in addrman deserialization");
352 nUBuckets ^= (1 << 30);
356 for (
int n = 0;
n <
nNew;
n++) {
360 info.nRandomPos =
vRandom.size();
365 int nUBucket = info.GetNewBucket(
nKey);
366 int nUBucketPos = info.GetBucketPosition(
nKey,
true, nUBucket);
367 if (
vvNew[nUBucket][nUBucketPos] == -1) {
368 vvNew[nUBucket][nUBucketPos] =
n;
381 int nKBucketPos = info.GetBucketPosition(
nKey,
false, nKBucket);
382 if (
vvTried[nKBucket][nKBucketPos] == -1) {
383 info.nRandomPos =
vRandom.size();
384 info.fInTried =
true;
397 for (
int bucket = 0; bucket < nUBuckets; bucket++) {
400 for (
int n = 0;
n < nSize;
n++) {
403 if (nIndex >= 0 && nIndex <
nNew) {
408 vvNew[bucket][nUBucketPos] = nIndex;
416 for (std::map<int, CAddrInfo>::const_iterator it =
mapInfo.begin(); it !=
mapInfo.end(); ) {
417 if (it->second.fInTried ==
false && it->second.nRefCount == 0) {
418 std::map<int, CAddrInfo>::const_iterator itCopy = it++;
425 if (nLost + nLostUnk > 0) {
426 LogPrint(
"addrman",
"addrman lost %i new and %i tried addresses due to collisions\n", nLostUnk, nLost);
439 std::vector<int>().swap(
vRandom);
443 vvNew[bucket][entry] = -1;
481 LogPrintf(
"ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n",
err);
508 for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
509 nAdd +=
Add_(*it,
source, nTimePenalty) ? 1 : 0;
558 std::vector<CAddress> vAddr;
588 #endif // BITCOIN_ADDRMAN_H std::vector< CAddress > GetAddr()
Return a bunch of addresses, selected at random.
int nNew
number of (unique) "new" entries
uint256 nKey
secret key to randomize bucket select with
void SerializationOp(Stream &s, Operation ser_action, int nType, int nVersion)
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
CAddrInfo Select_(bool newOnly)
Select an address to connect to, if newOnly is set to true, only the new table is selected from...
int nIdCount
last used nId
void Connected_(const CService &addr, int64_t nTime)
Mark an entry as currently-connected-to.
size_t size() const
Return the number of (unique) addresses in all tables.
void Good(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as accessible.
void Attempt_(const CService &addr, int64_t nTime)
Mark an entry as attempted to connect.
std::map< int, CAddrInfo > mapInfo
table with information about all nIds
void ClearNew(int nUBucket, int nUBucketPos)
Clear a position in a "new" table. This is the only place where entries are actually deleted...
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2)
Swap two elements in vRandom.
#define ADDRMAN_TRIED_BUCKET_COUNT
total number of buckets for tried addresses
bool Add(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty=0)
Add a single address.
int nRandomPos
position in vRandom
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)
void Good_(const CService &addr, int64_t nTime)
Mark an entry "good", possibly moving it from "new" to "tried".
CAddrInfo Select(bool newOnly=false)
bool fInTried
in tried set? (memory only)
CCriticalSection cs
critical section to protect the inner data structures
std::string ToStringIPPort(bool fUseGetnameinfo=true) const
std::map< CNetAddr, int > mapAddr
find an nId based on its network address
static int LogPrint(const char *category, const char *format)
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
void Serialize(Stream &s, int nType, int nVersionDummy) const
bool Add_(const CAddress &addr, const CNetAddr &source, int64_t nTimePenalty)
Add an entry to the "new" table.
void SetServices_(const CService &addr, ServiceFlags nServices)
Update an entry's service bits.
std::vector< int > vRandom
randomly-ordered vector of all nIds
#define ADDRMAN_BUCKET_SIZE
maximum allowed number of entries in buckets for new and tried addresses
int GetNewBucket(const uint256 &nKey, const CNetAddr &src) const
Calculate in which "new" bucket this entry belongs, given a certain source.
int GetNewBucket(const uint256 &nKey) const
Calculate in which "new" bucket this entry belongs, using its default source.
CAddrInfo * Find(const CNetAddr &addr, int *pnId=NULL)
Find an entry.
void SetServices(const CService &addr, ServiceFlags nServices)
void Delete(int nId)
Delete an entry. It must not be in tried, and have refcount 0.
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE]
list of "tried" buckets
void Check()
Consistency check.
double GetChance(int64_t nNow=GetAdjustedTime()) const
Calculate the relative chance this entry should be given when selecting nodes to connect to...
void Connected(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as currently-connected-to.
virtual int RandomInt(int nMax)
Wraps GetRandInt to allow tests to override RandomInt and make it determinismistic.
void Unserialize(Stream &s, int nType, int nVersionDummy)
void MakeTried(CAddrInfo &info, int nId)
Move an entry from the "new" table(s) to the "tried" table.
unsigned int GetSerializeSize(int nType, int nVersion) const
void GetAddr_(std::vector< CAddress > &vAddr)
Select several addresses at once.
#define ADDRMAN_NEW_BUCKET_COUNT
total number of buckets for new addresses
int64_t GetAdjustedTime()
int64_t nLastSuccess
last successful connection by us
CNetAddr source
where knowledge about this address first came from
int nRefCount
reference count in new sets (memory only)
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64_t nTimePenalty=0)
Add multiple addresses.
int nAttempts
connection attempts since last successful attempt
void Attempt(const CService &addr, int64_t nTime=GetAdjustedTime())
Mark an entry as connection attempted to.
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=NULL)
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS
in how many buckets for entries with new addresses a single address may occur
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE]
list of "new" buckets
int GetTriedBucket(const uint256 &nKey) const
Calculate in which "tried" bucket this entry belongs.