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 | ||||