Changeset View
Changeset View
Standalone View
Standalone View
src/seeder/db.h
Show All 18 Lines | |||||
#define REQUIRE_VERSION 70001 | #define REQUIRE_VERSION 70001 | ||||
static inline int GetRequireHeight(const bool testnet = fTestNet) { | static inline int GetRequireHeight(const bool testnet = fTestNet) { | ||||
return testnet ? 500000 : 350000; | return testnet ? 500000 : 350000; | ||||
} | } | ||||
static inline std::string ToString(const CService &ip) { | static inline std::string ToString(const CService &ip) { | ||||
std::string str = ip.ToString(); | std::string str = ip.ToString(); | ||||
while (str.size() < 22) | while (str.size() < 22) { | ||||
str += ' '; | str += ' '; | ||||
} | |||||
return str; | return str; | ||||
} | } | ||||
class CAddrStat { | class CAddrStat { | ||||
private: | private: | ||||
float weight; | float weight; | ||||
float count; | float count; | ||||
float reliability; | float reliability; | ||||
▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | bool IsGood() const { | ||||
if (stat2H.reliability > 0.85 && stat2H.count > 2) return true; | if (stat2H.reliability > 0.85 && stat2H.count > 2) return true; | ||||
if (stat8H.reliability > 0.70 && stat8H.count > 4) return true; | if (stat8H.reliability > 0.70 && stat8H.count > 4) return true; | ||||
if (stat1D.reliability > 0.55 && stat1D.count > 8) return true; | if (stat1D.reliability > 0.55 && stat1D.count > 8) return true; | ||||
if (stat1W.reliability > 0.45 && stat1W.count > 16) return true; | if (stat1W.reliability > 0.45 && stat1W.count > 16) return true; | ||||
if (stat1M.reliability > 0.35 && stat1M.count > 32) return true; | if (stat1M.reliability > 0.35 && stat1M.count > 32) return true; | ||||
return false; | return false; | ||||
} | } | ||||
int GetBanTime() const { | int GetBanTime() const { | ||||
if (IsGood()) return 0; | if (IsGood()) { | ||||
return 0; | |||||
} | |||||
if (clientVersion && clientVersion < 31900) { | if (clientVersion && clientVersion < 31900) { | ||||
return 604800; | return 604800; | ||||
} | } | ||||
if (stat1M.reliability - stat1M.weight + 1.0 < 0.15 && | if (stat1M.reliability - stat1M.weight + 1.0 < 0.15 && | ||||
stat1M.count > 32) { | stat1M.count > 32) { | ||||
return 30 * 86400; | return 30 * 86400; | ||||
} | } | ||||
if (stat1W.reliability - stat1W.weight + 1.0 < 0.10 && | if (stat1W.reliability - stat1W.weight + 1.0 < 0.10 && | ||||
stat1W.count > 16) { | stat1W.count > 16) { | ||||
return 7 * 86400; | return 7 * 86400; | ||||
} | } | ||||
if (stat1D.reliability - stat1D.weight + 1.0 < 0.05 && | if (stat1D.reliability - stat1D.weight + 1.0 < 0.05 && | ||||
stat1D.count > 8) { | stat1D.count > 8) { | ||||
return 1 * 86400; | return 1 * 86400; | ||||
} | } | ||||
return 0; | return 0; | ||||
} | } | ||||
int GetIgnoreTime() const { | int GetIgnoreTime() const { | ||||
if (IsGood()) return 0; | if (IsGood()) { | ||||
return 0; | |||||
} | |||||
if (stat1M.reliability - stat1M.weight + 1.0 < 0.20 && | if (stat1M.reliability - stat1M.weight + 1.0 < 0.20 && | ||||
stat1M.count > 2) { | stat1M.count > 2) { | ||||
return 10 * 86400; | return 10 * 86400; | ||||
} | } | ||||
if (stat1W.reliability - stat1W.weight + 1.0 < 0.16 && | if (stat1W.reliability - stat1W.weight + 1.0 < 0.16 && | ||||
stat1W.count > 2) { | stat1W.count > 2) { | ||||
return 3 * 86400; | return 3 * 86400; | ||||
} | } | ||||
Show All 18 Lines | public: | ||||
inline void SerializationOp(Stream &s, Operation ser_action) { | inline void SerializationOp(Stream &s, Operation ser_action) { | ||||
uint8_t version = 4; | uint8_t version = 4; | ||||
READWRITE(version); | READWRITE(version); | ||||
READWRITE(ip); | READWRITE(ip); | ||||
READWRITE(services); | READWRITE(services); | ||||
READWRITE(lastTry); | READWRITE(lastTry); | ||||
uint8_t tried = ourLastTry != 0; | uint8_t tried = ourLastTry != 0; | ||||
READWRITE(tried); | READWRITE(tried); | ||||
if (tried) { | if (!tried) { | ||||
return; | |||||
} | |||||
READWRITE(ourLastTry); | READWRITE(ourLastTry); | ||||
READWRITE(ignoreTill); | READWRITE(ignoreTill); | ||||
READWRITE(stat2H); | READWRITE(stat2H); | ||||
READWRITE(stat8H); | READWRITE(stat8H); | ||||
READWRITE(stat1D); | READWRITE(stat1D); | ||||
READWRITE(stat1W); | READWRITE(stat1W); | ||||
if (version >= 1) { | if (version >= 1) { | ||||
READWRITE(stat1M); | READWRITE(stat1M); | ||||
} else if (!ser_action.ForRead()) { | } else if (!ser_action.ForRead()) { | ||||
*((CAddrStat *)(&stat1M)) = stat1W; | *((CAddrStat *)(&stat1M)) = stat1W; | ||||
} | } | ||||
READWRITE(total); | READWRITE(total); | ||||
READWRITE(success); | READWRITE(success); | ||||
READWRITE(clientVersion); | READWRITE(clientVersion); | ||||
if (version >= 2) READWRITE(clientSubVersion); | if (version >= 2) READWRITE(clientSubVersion); | ||||
if (version >= 3) READWRITE(blocks); | if (version >= 3) READWRITE(blocks); | ||||
if (version >= 4) READWRITE(ourLastSuccess); | if (version >= 4) READWRITE(ourLastSuccess); | ||||
} | } | ||||
} | |||||
}; | }; | ||||
class CAddrDbStats { | class CAddrDbStats { | ||||
public: | public: | ||||
int nBanned; | int nBanned; | ||||
int nAvail; | int nAvail; | ||||
int nTracked; | int nTracked; | ||||
int nNew; | int nNew; | ||||
int nGood; | int nGood; | ||||
int nAge; | int nAge; | ||||
}; | }; | ||||
struct CServiceResult { | struct CServiceResult { | ||||
CService service; | CService service; | ||||
bool fGood; | bool fGood; | ||||
int nBanTime; | int nBanTime; | ||||
int nHeight; | int nHeight; | ||||
int nClientV; | int nClientV; | ||||
std::string strClientV; | std::string strClientV; | ||||
int64_t ourLastSuccess; | int64_t ourLastSuccess; | ||||
}; | }; | ||||
// seen nodes | /** | ||||
// / \ | * seen nodes | ||||
// (a) banned nodes available nodes-------------- | * / \ | ||||
// / | \ | * (a) banned nodes available nodes-------------- | ||||
// tracked nodes (b) unknown nodes (e) active nodes | * / | \ | ||||
// / \ | * tracked nodes (b) unknown nodes (e) active nodes | ||||
// (d) good nodes (c) non-good nodes | * / \ | ||||
* (d) good nodes (c) non-good nodes | |||||
*/ | |||||
class CAddrDb { | class CAddrDb { | ||||
private: | private: | ||||
mutable CCriticalSection cs; | mutable CCriticalSection cs; | ||||
// number of address id's | // number of address id's | ||||
int nId; | int nId; | ||||
// map address id to address info (b,c,d,e) | // map address id to address info (b,c,d,e) | ||||
std::map<int, CAddrInfo> idToInfo; | std::map<int, CAddrInfo> idToInfo; | ||||
// map ip to id (b,c,d,e) | // map ip to id (b,c,d,e) | ||||
Show All 20 Lines | protected: | ||||
// mark an IP as bad (and optionally ban it) (must have been returned by | // mark an IP as bad (and optionally ban it) (must have been returned by | ||||
// Get_) | // Get_) | ||||
void Bad_(const CService &ip, int ban); | void Bad_(const CService &ip, int ban); | ||||
// mark an IP as skipped (must have been returned by Get_) | // mark an IP as skipped (must have been returned by Get_) | ||||
void Skipped_(const CService &ip); | void Skipped_(const CService &ip); | ||||
// look up id of an IP | // look up id of an IP | ||||
int Lookup_(const CService &ip); | int Lookup_(const CService &ip); | ||||
// get a random set of IPs (shared lock only) | // get a random set of IPs (shared lock only) | ||||
void GetIPs_(std::set<CNetAddr> &ips, uint64_t requestedFlags, int max, | void GetIPs_(std::set<CNetAddr> &ips, uint64_t requestedFlags, uint32_t max, | ||||
const bool *nets); | const bool *nets); | ||||
public: | public: | ||||
// nodes that are banned, with their unban time (a) | // nodes that are banned, with their unban time (a) | ||||
std::map<CService, time_t> banned; | std::map<CService, time_t> banned; | ||||
void GetStats(CAddrDbStats &stats) { | void GetStats(CAddrDbStats &stats) { | ||||
LOCK(cs); | LOCK(cs); | ||||
Show All 27 Lines | public: | ||||
// serialization code | // serialization code | ||||
// format: | // format: | ||||
// nVersion (0 for now) | // nVersion (0 for now) | ||||
// n (number of ips in (b,c,d)) | // n (number of ips in (b,c,d)) | ||||
// CAddrInfo[n] | // CAddrInfo[n] | ||||
// banned | // banned | ||||
// acquires a shared lock (this does not suffice for read mode, but we | // acquires a shared lock (this does not suffice for read mode, but we | ||||
// assume that only happens at startup, single-threaded) | // assume that only happens at startup, single-threaded) this way, dumping | ||||
// this way, dumping does not interfere with GetIPs_, which is called from | // does not interfere with GetIPs_, which is called from the DNS thread | ||||
// the DNS thread | |||||
template <typename Stream> void Serialize(Stream &s) const { | template <typename Stream> void Serialize(Stream &s) const { | ||||
LOCK(cs); | LOCK(cs); | ||||
int nVersion = 0; | int nVersion = 0; | ||||
s << nVersion; | s << nVersion; | ||||
CAddrDb *db = const_cast<CAddrDb *>(this); | CAddrDb *db = const_cast<CAddrDb *>(this); | ||||
int n = ourId.size() + unkId.size(); | int n = ourId.size() + unkId.size(); | ||||
Show All 40 Lines | template <typename Stream> void Unserialize(Stream &s) { | ||||
s >> banned; | s >> banned; | ||||
} | } | ||||
void Add(const CAddress &addr, bool fForce = false) { | void Add(const CAddress &addr, bool fForce = false) { | ||||
LOCK(cs); | LOCK(cs); | ||||
Add_(addr, fForce); | Add_(addr, fForce); | ||||
} | } | ||||
void Add(const std::vector<CAddress> &vAddr, bool fForce = false) { | void Add(const std::vector<CAddress> &vAddr, bool fForce = false) { | ||||
LOCK(cs); | LOCK(cs); | ||||
for (size_t i = 0; i < vAddr.size(); i++) { | for (size_t i = 0; i < vAddr.size(); i++) { | ||||
Add_(vAddr[i], fForce); | Add_(vAddr[i], fForce); | ||||
} | } | ||||
} | } | ||||
void Good(const CService &addr, int clientVersion, | void Good(const CService &addr, int clientVersion, | ||||
std::string clientSubVersion, int blocks) { | std::string clientSubVersion, int blocks) { | ||||
LOCK(cs); | LOCK(cs); | ||||
Good_(addr, clientVersion, clientSubVersion, blocks); | Good_(addr, clientVersion, clientSubVersion, blocks); | ||||
} | } | ||||
void Skipped(const CService &addr) { | void Skipped(const CService &addr) { | ||||
LOCK(cs); | LOCK(cs); | ||||
Skipped_(addr); | Skipped_(addr); | ||||
} | } | ||||
void Bad(const CService &addr, int ban = 0) { | void Bad(const CService &addr, int ban = 0) { | ||||
LOCK(cs); | LOCK(cs); | ||||
Bad_(addr, ban); | Bad_(addr, ban); | ||||
} | } | ||||
bool Get(CServiceResult &ip, int &wait) { | bool Get(CServiceResult &ip, int &wait) { | ||||
LOCK(cs); | LOCK(cs); | ||||
return Get_(ip, wait); | return Get_(ip, wait); | ||||
} | } | ||||
void GetMany(std::vector<CServiceResult> &ips, int max, int &wait) { | void GetMany(std::vector<CServiceResult> &ips, int max, int &wait) { | ||||
LOCK(cs); | LOCK(cs); | ||||
while (max > 0) { | while (max > 0) { | ||||
CServiceResult ip = {}; | CServiceResult ip = {}; | ||||
if (!Get_(ip, wait)) return; | if (!Get_(ip, wait)) { | ||||
return; | |||||
} | |||||
ips.push_back(ip); | ips.push_back(ip); | ||||
max--; | max--; | ||||
} | } | ||||
} | } | ||||
void ResultMany(const std::vector<CServiceResult> &ips) { | void ResultMany(const std::vector<CServiceResult> &ips) { | ||||
LOCK(cs); | LOCK(cs); | ||||
for (int i = 0; i < ips.size(); i++) { | for (size_t i = 0; i < ips.size(); i++) { | ||||
if (ips[i].fGood) { | if (ips[i].fGood) { | ||||
Good_(ips[i].service, ips[i].nClientV, ips[i].strClientV, | Good_(ips[i].service, ips[i].nClientV, ips[i].strClientV, | ||||
ips[i].nHeight); | ips[i].nHeight); | ||||
} else { | } else { | ||||
Bad_(ips[i].service, ips[i].nBanTime); | Bad_(ips[i].service, ips[i].nBanTime); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
void GetIPs(std::set<CNetAddr> &ips, uint64_t requestedFlags, int max, | |||||
void GetIPs(std::set<CNetAddr> &ips, uint64_t requestedFlags, uint32_t max, | |||||
const bool *nets) { | const bool *nets) { | ||||
LOCK(cs); | LOCK(cs); | ||||
GetIPs_(ips, requestedFlags, max, nets); | GetIPs_(ips, requestedFlags, max, nets); | ||||
} | } | ||||
}; | }; | ||||
#endif | #endif |