4 #ifndef _BITCOIN_ADDRMAN
5 #define _BITCOIN_ADDRMAN 1
16 #include <openssl/rand.h>
123 #define ADDRMAN_TRIED_BUCKET_COUNT 64
126 #define ADDRMAN_TRIED_BUCKET_SIZE 64
129 #define ADDRMAN_NEW_BUCKET_COUNT 256
132 #define ADDRMAN_NEW_BUCKET_SIZE 64
135 #define ADDRMAN_TRIED_BUCKETS_PER_GROUP 4
138 #define ADDRMAN_NEW_BUCKETS_PER_SOURCE_GROUP 32
141 #define ADDRMAN_NEW_BUCKETS_PER_ADDRESS 4
144 #define ADDRMAN_TRIED_ENTRIES_INSPECT_ON_EVICT 4
147 #define ADDRMAN_HORIZON_DAYS 30
150 #define ADDRMAN_RETRIES 3
153 #define ADDRMAN_MAX_FAILURES 10
156 #define ADDRMAN_MIN_FAIL_DAYS 7
159 #define ADDRMAN_GETADDR_MAX_PCT 23
162 #define ADDRMAN_GETADDR_MAX 2500
172 std::vector<unsigned char>
nKey;
208 void SwapRandom(
unsigned int nRandomPos1,
unsigned int nRandomPos2);
241 void GetAddr_(std::vector<CAddress> &vAddr);
272 unsigned char nVersion = 0;
283 std::map<int, int> mapUnkIds;
285 for (std::map<int, CAddrInfo>::iterator it = am->
mapInfo.begin(); it != am->
mapInfo.end(); it++)
287 if (nIds == nNew)
break;
288 mapUnkIds[(*it).first] = nIds;
297 for (std::map<int, CAddrInfo>::iterator it = am->
mapInfo.begin(); it != am->
mapInfo.end(); it++)
299 if (nIds == nTried)
break;
307 for (std::vector<std::set<int> >::iterator it = am->
vvNew.begin(); it != am->
vvNew.end(); it++)
309 const std::set<int> &vNew = (*it);
310 int nSize = vNew.size();
312 for (std::set<int>::iterator it2 = vNew.begin(); it2 != vNew.end(); it2++)
314 int nIndex = mapUnkIds[*it2];
327 for (
int n = 0; n < am->
nNew; n++)
334 if (nUBuckets != ADDRMAN_NEW_BUCKET_COUNT)
342 for (
int n = 0; n < am->
nTried; n++)
361 for (
int b = 0; b < nUBuckets; b++)
363 std::set<int> &vNew = am->
vvNew[b];
366 for (
int n = 0; n < nSize; n++)
385 RAND_bytes(&nKey[0], 32);
395 return vRandom.size();
406 printf(
"ADDRMAN CONSISTENCY CHECK FAILED!!! err=%i\n", err);
418 fRet |=
Add_(addr, source, nTimePenalty);
427 bool Add(
const std::vector<CAddress> &vAddr,
const CNetAddr& source,
int64 nTimePenalty = 0)
433 for (std::vector<CAddress>::const_iterator it = vAddr.begin(); it != vAddr.end(); it++)
434 nAdd +=
Add_(*it, source, nTimePenalty) ? 1 : 0;
482 std::vector<CAddress> vAddr;
int GetNewBucket(const std::vector< unsigned char > &nKey, const CNetAddr &src) const
bool Add_(const CAddress &addr, const CNetAddr &source, int64 nTimePenalty)
CAddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=NULL)
std::string ToStringIPPort() const
CAddress Select_(int nUnkBias)
bool Add(const CAddress &addr, const CNetAddr &source, int64 nTimePenalty=0)
#define ADDRMAN_TRIED_BUCKET_COUNT
CAddrInfo * Find(const CNetAddr &addr, int *pnId=NULL)
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, int64 nTimePenalty=0)
Stochastical (IP) address manager.
std::vector< CAddress > GetAddr()
Extended statistics about a CAddress.
std::vector< int > vRandom
int SelectTried(int nKBucket)
std::vector< std::set< int > > vvNew
A combination of a network address (CNetAddr) and a (TCP) port.
void MakeTried(CAddrInfo &info, int nId, int nOrigin)
A CService with information about it as peer.
double GetChance(int64 nNow=GetAdjustedTime()) const
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2)
void Attempt(const CService &addr, int64 nTime=GetAdjustedTime())
void Connected_(const CService &addr, int64 nTime)
int ShrinkNew(int nUBucket)
std::map< CNetAddr, int > mapAddr
IMPLEMENT_SERIALIZE(CAddress *pthis=(CAddress *)(this);READWRITE(*pthis);READWRITE(source);READWRITE(nLastSuccess);READWRITE(nAttempts);) void Init()
void Connected(const CService &addr, int64 nTime=GetAdjustedTime())
#define ADDRMAN_TRIED_BUCKET_SIZE
std::vector< std::vector< int > > vvTried
IP address (IPv6, or IPv4 using mapped IPv6 range (::FFFF:0:0/96))
void Good_(const CService &addr, int64 nTime)
bool IsTerrible(int64 nNow=GetAdjustedTime()) const
std::vector< unsigned char > nKey
CAddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
#define ADDRMAN_NEW_BUCKET_COUNT
int GetTriedBucket(const std::vector< unsigned char > &nKey) const
void Good(const CService &addr, int64 nTime=GetAdjustedTime())
CAddress Select(int nUnkBias=50)
void GetAddr_(std::vector< CAddress > &vAddr)
void Attempt_(const CService &addr, int64 nTime)
std::map< int, CAddrInfo > mapInfo
int GetNewBucket(const std::vector< unsigned char > &nKey) const
std::string ToString() const
IMPLEMENT_SERIALIZE(({{LOCK(cs);unsigned char nVersion=0;READWRITE(nVersion);READWRITE(nKey);READWRITE(nNew);READWRITE(nTried);CAddrMan *am=const_cast< CAddrMan * >(this);if(fWrite){int nUBuckets=ADDRMAN_NEW_BUCKET_COUNT;READWRITE(nUBuckets);std::map< int, int > mapUnkIds;int nIds=0;for(std::map< int, CAddrInfo >::iterator it=am->mapInfo.begin();it!=am->mapInfo.end();it++){if(nIds==nNew) break;mapUnkIds[(*it).first]=nIds;CAddrInfo &info=(*it).second;if(info.nRefCount){READWRITE(info);nIds++;}}nIds=0;for(std::map< int, CAddrInfo >::iterator it=am->mapInfo.begin();it!=am->mapInfo.end();it++){if(nIds==nTried) break;CAddrInfo &info=(*it).second;if(info.fInTried){READWRITE(info);nIds++;}}for(std::vector< std::set< int > >::iterator it=am->vvNew.begin();it!=am->vvNew.end();it++){const std::set< int > &vNew=(*it);int nSize=vNew.size();READWRITE(nSize);for(std::set< int >::iterator it2=vNew.begin();it2!=vNew.end();it2++){int nIndex=mapUnkIds[*it2];READWRITE(nIndex);}}}else{int nUBuckets=0;READWRITE(nUBuckets);am->nIdCount=0;am->mapInfo.clear();am->mapAddr.clear();am->vRandom.clear();am->vvTried=std::vector< std::vector< int > >(ADDRMAN_TRIED_BUCKET_COUNT, std::vector< int >(0));am->vvNew=std::vector< std::set< int > >(ADDRMAN_NEW_BUCKET_COUNT, std::set< int >());for(int n=0;n< am->nNew;n++){CAddrInfo &info=am->mapInfo[n];READWRITE(info);am->mapAddr[info]=n;info.nRandomPos=vRandom.size();am->vRandom.push_back(n);if(nUBuckets!=ADDRMAN_NEW_BUCKET_COUNT){am->vvNew[info.GetNewBucket(am->nKey)].insert(n);info.nRefCount++;}}am->nIdCount=am->nNew;int nLost=0;for(int n=0;n< am->nTried;n++){CAddrInfo info;READWRITE(info);std::vector< int > &vTried=am->vvTried[info.GetTriedBucket(am->nKey)];if(vTried.size()< ADDRMAN_TRIED_BUCKET_SIZE){info.nRandomPos=vRandom.size();info.fInTried=true;am->vRandom.push_back(am->nIdCount);am->mapInfo[am->nIdCount]=info;am->mapAddr[info]=am->nIdCount;vTried.push_back(am->nIdCount);am->nIdCount++;}else{nLost++;}}am->nTried-=nLost;for(int b=0;b< nUBuckets;b++){std::set< int > &vNew=am->vvNew[b];int nSize=0;READWRITE(nSize);for(int n=0;n< nSize;n++){int nIndex=0;READWRITE(nIndex);CAddrInfo &info=am->mapInfo[nIndex];if(nUBuckets==ADDRMAN_NEW_BUCKET_COUNT &&info.nRefCount< ADDRMAN_NEW_BUCKETS_PER_ADDRESS){info.nRefCount++;vNew.insert(nIndex);}}}}}});) CAddrMan()
#define ADDRMAN_NEW_BUCKETS_PER_ADDRESS