Bitcoin ABC 0.30.5
P2P Digital Currency
addrman_impl.h
Go to the documentation of this file.
1// Copyright (c) 2021 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#ifndef BITCOIN_ADDRMAN_IMPL_H
6#define BITCOIN_ADDRMAN_IMPL_H
7
8#include <logging.h>
9#include <logging/timer.h>
10#include <netaddress.h>
11#include <protocol.h>
12#include <serialize.h>
13#include <sync.h>
14#include <timedata.h>
15#include <uint256.h>
16#include <util/time.h>
17
18#include <cstdint>
19#include <optional>
20#include <set>
21#include <unordered_map>
22#include <unordered_set>
23#include <utility>
24#include <vector>
25
27static constexpr int32_t ADDRMAN_TRIED_BUCKET_COUNT_LOG2{8};
28static constexpr int ADDRMAN_TRIED_BUCKET_COUNT{
30
32static constexpr int32_t ADDRMAN_NEW_BUCKET_COUNT_LOG2{10};
33static constexpr int ADDRMAN_NEW_BUCKET_COUNT{1
35
37static constexpr int32_t ADDRMAN_BUCKET_SIZE_LOG2{6};
39
43class AddrInfo : public CAddress {
44public:
47
50
53
56
58 int nAttempts{0};
59
61 int nRefCount{0};
62
64 bool fInTried{false};
65
67 mutable int nRandomPos{-1};
68
71 READWRITE(obj.source,
72 Using<ChronoFormatter<int64_t>>(obj.m_last_success),
73 obj.nAttempts);
74 }
75
76 AddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
77 : CAddress(addrIn), source(addrSource) {}
78
80
82 int GetTriedBucket(const uint256 &nKey,
83 const std::vector<bool> &asmap) const;
84
87 int GetNewBucket(const uint256 &nKey, const CNetAddr &src,
88 const std::vector<bool> &asmap) const;
89
92 int GetNewBucket(const uint256 &nKey,
93 const std::vector<bool> &asmap) const {
94 return GetNewBucket(nKey, source, asmap);
95 }
96
98 int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const;
99
102 bool IsTerrible(NodeSeconds now = Now<NodeSeconds>()) const;
103
106 double GetChance(NodeSeconds now = Now<NodeSeconds>()) const;
107};
108
110public:
111 AddrManImpl(std::vector<bool> &&asmap, int32_t consistency_check_ratio);
112
113 ~AddrManImpl();
114
115 template <typename Stream>
116 void Serialize(Stream &s_) const EXCLUSIVE_LOCKS_REQUIRED(!cs);
117
118 template <typename Stream>
119 void Unserialize(Stream &s_) EXCLUSIVE_LOCKS_REQUIRED(!cs);
120
121 size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs);
122
123 bool Add(const std::vector<CAddress> &vAddr, const CNetAddr &source,
124 std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(!cs);
125
126 void Good(const CService &addr, bool test_before_evict, NodeSeconds time)
128
129 void Attempt(const CService &addr, bool fCountFailure, NodeSeconds time)
131
133
134 std::pair<CAddress, NodeSeconds> SelectTriedCollision()
136
137 std::pair<CAddress, NodeSeconds> Select(bool newOnly) const
139
140 std::vector<CAddress> GetAddr(size_t max_addresses, size_t max_pct,
141 std::optional<Network> network) const
143
144 void Connected(const CService &addr, NodeSeconds time)
146
147 void SetServices(const CService &addr, ServiceFlags nServices)
149
150 const std::vector<bool> &GetAsmap() const;
151
153
155
156 friend class AddrManTest;
157 friend class AddrManCorrupted;
158
159private:
161 mutable Mutex cs;
162
165
168
170 enum Format : uint8_t {
181 };
182
188 static constexpr Format FILE_FORMAT = Format::V4_MULTIPORT;
189
196 static constexpr uint8_t INCOMPATIBILITY_BASE = 32;
197
199 int nIdCount GUARDED_BY(cs);
200
202 std::unordered_map<int, AddrInfo> mapInfo GUARDED_BY(cs);
203
205 std::unordered_map<CService, int, CServiceHash> mapAddr GUARDED_BY(cs);
206
210 mutable std::vector<int> vRandom GUARDED_BY(cs);
211
212 // number of "tried" entries
213 int nTried GUARDED_BY(cs);
214
217
219 int nNew GUARDED_BY(cs);
220
223
226
229 std::set<int> m_tried_collisions;
230
236
237 // Compressed IP->ASN mapping, loaded from a file when a node starts.
238 // Should be always empty if no file was provided.
239 // This mapping is then used for bucketing nodes in Addrman.
240 //
241 // If asmap is provided, nodes will be bucketed by
242 // AS they belong to, in order to make impossible for a node
243 // to connect to several nodes hosted in a single AS.
244 // This is done in response to Erebus attack, but also to generally
245 // diversify the connections every node creates,
246 // especially useful when a large fraction of nodes
247 // operate under a couple of cloud providers.
248 //
249 // If a new asmap was provided, the existing records
250 // would be re-bucketed accordingly.
251 const std::vector<bool> m_asmap;
252
255 bool deterministic = false;
256
258 AddrInfo *Find(const CService &addr, int *pnId = nullptr)
260
263 AddrInfo *Create(const CAddress &addr, const CNetAddr &addrSource,
264 int *pnId = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs);
265
267 void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) const
269
271 void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
272
275 void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs);
276
278 void MakeTried(AddrInfo &info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs);
279
284 bool AddSingle(const CAddress &addr, const CNetAddr &source,
285 std::chrono::seconds time_penalty)
287
288 void Good_(const CService &addr, bool test_before_evict, NodeSeconds time)
290
291 bool Add_(const std::vector<CAddress> &vAddr, const CNetAddr &source,
292 std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs);
293
294 void Attempt_(const CService &addr, bool fCountFailure, NodeSeconds time)
296
297 std::pair<CAddress, NodeSeconds> Select_(bool newOnly) const
299
300 std::vector<CAddress> GetAddr_(size_t max_addresses, size_t max_pct,
301 std::optional<Network> network) const
303
304 void Connected_(const CService &addr, NodeSeconds time)
306
307 void SetServices_(const CService &addr, ServiceFlags nServices)
309
311
314
317 void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs);
318
322};
323
324#endif // BITCOIN_ADDRMAN_IMPL_H
static constexpr int ADDRMAN_TRIED_BUCKET_COUNT
Definition: addrman_impl.h:28
static constexpr int32_t ADDRMAN_TRIED_BUCKET_COUNT_LOG2
Total number of buckets for tried addresses.
Definition: addrman_impl.h:27
static constexpr int32_t ADDRMAN_BUCKET_SIZE_LOG2
Maximum allowed number of entries in buckets for new and tried addresses.
Definition: addrman_impl.h:37
static constexpr int32_t ADDRMAN_NEW_BUCKET_COUNT_LOG2
Total number of buckets for new addresses.
Definition: addrman_impl.h:32
static constexpr int ADDRMAN_BUCKET_SIZE
Definition: addrman_impl.h:38
static constexpr int ADDRMAN_NEW_BUCKET_COUNT
Definition: addrman_impl.h:33
Extended statistics about a CAddress.
Definition: addrman_impl.h:43
int GetTriedBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "tried" bucket this entry belongs.
Definition: addrman.cpp:55
int nRandomPos
position in vRandom
Definition: addrman_impl.h:67
CNetAddr source
where knowledge about this address first came from
Definition: addrman_impl.h:52
int GetNewBucket(const uint256 &nKey, const std::vector< bool > &asmap) const
Calculate in which "new" bucket this entry belongs, using its default source.
Definition: addrman_impl.h:92
bool fInTried
in tried set? (memory only)
Definition: addrman_impl.h:64
SERIALIZE_METHODS(AddrInfo, obj)
Definition: addrman_impl.h:69
NodeSeconds m_last_success
last successful connection by us
Definition: addrman_impl.h:55
int GetNewBucket(const uint256 &nKey, const CNetAddr &src, const std::vector< bool > &asmap) const
Calculate in which "new" bucket this entry belongs, given a certain source.
Definition: addrman.cpp:64
NodeSeconds m_last_count_attempt
last counted attempt (memory only)
Definition: addrman_impl.h:49
NodeSeconds m_last_try
last try whatsoever by us (memory only)
Definition: addrman_impl.h:46
double GetChance(NodeSeconds now=Now< NodeSeconds >()) const
Calculate the relative chance this entry should be given when selecting nodes to connect to.
Definition: addrman.cpp:117
bool IsTerrible(NodeSeconds now=Now< NodeSeconds >()) const
Determine whether the statistics about this entry are bad enough so that it can just be deleted.
Definition: addrman.cpp:86
AddrInfo(const CAddress &addrIn, const CNetAddr &addrSource)
Definition: addrman_impl.h:76
int nRefCount
reference count in new sets (memory only)
Definition: addrman_impl.h:61
int GetBucketPosition(const uint256 &nKey, bool fNew, int nBucket) const
Calculate in which position of a bucket to store this entry.
Definition: addrman.cpp:77
int nAttempts
connection attempts since last successful attempt
Definition: addrman_impl.h:58
void ClearNew(int nUBucket, int nUBucketPos) EXCLUSIVE_LOCKS_REQUIRED(cs)
Clear a position in a "new" table.
Definition: addrman.cpp:504
std::unordered_map< CService, int, CServiceHash > mapAddr GUARDED_BY(cs)
find an nId based on its network address and port.
std::pair< CAddress, NodeSeconds > Select(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1219
friend class AddrManCorrupted
Definition: addrman_impl.h:157
void Connected_(const CService &addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:900
void Attempt_(const CService &addr, bool fCountFailure, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:743
static constexpr Format FILE_FORMAT
The maximum format this software knows it can unserialize.
Definition: addrman_impl.h:188
void ResolveCollisions_() EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:935
int nNew GUARDED_BY(cs)
number of (unique) "new" entries
Format
Serialization versions.
Definition: addrman_impl.h:170
@ V4_MULTIPORT
adds support for multiple ports per IP
Definition: addrman_impl.h:180
@ V0_HISTORICAL
historic format, before commit e6b343d88
Definition: addrman_impl.h:172
@ V3_BIP155
same as V2_ASMAP plus addresses are in BIP155 format
Definition: addrman_impl.h:178
@ V2_ASMAP
for files including asmap version
Definition: addrman_impl.h:176
@ V1_DETERMINISTIC
for pre-asmap files
Definition: addrman_impl.h:174
void Serialize(Stream &s_) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:141
void Connected(const CService &addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1237
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1228
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs)
list of "new" buckets
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs)
list of "tried" buckets
size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1172
void MakeTried(AddrInfo &info, int nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Move an entry from the "new" table(s) to the "tried" table.
Definition: addrman.cpp:522
void SetServices(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1244
AddrManImpl(std::vector< bool > &&asmap, int32_t consistency_check_ratio)
Definition: addrman.cpp:132
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:919
int nTried GUARDED_BY(cs)
const int32_t m_consistency_check_ratio
Perform consistency checks every m_consistency_check_ratio operations (if non-zero).
Definition: addrman_impl.h:235
const std::vector< bool > & GetAsmap() const
Definition: addrman.cpp:1251
std::unordered_map< int, AddrInfo > mapInfo GUARDED_BY(cs)
table with information about all nIds
void MakeDeterministic() EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1285
void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Consistency check, taking into account m_consistency_check_ratio.
Definition: addrman.cpp:1046
NodeSeconds m_last_good GUARDED_BY(cs)
last time Good was called (memory only)
int CheckAddrman() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Perform consistency check, regardless of m_consistency_check_ratio.
Definition: addrman.cpp:1064
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1178
AddrInfo * Find(const CService &addr, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Find an entry.
Definition: addrman.cpp:432
Mutex cs
A mutex to protect the inner data structures.
Definition: addrman_impl.h:161
std::pair< CAddress, NodeSeconds > SelectTriedCollision_() EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:1016
std::pair< CAddress, NodeSeconds > Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:764
std::pair< CAddress, NodeSeconds > SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1211
bool deterministic
Use deterministic bucket selection and inner loops randomization.
Definition: addrman_impl.h:255
friend class AddrManTest
Definition: addrman_impl.h:156
void Good_(const CService &addr, bool test_before_evict, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:665
static constexpr uint8_t INCOMPATIBILITY_BASE
The initial value of a field that is incremented every time an incompatible format change is made (su...
Definition: addrman_impl.h:196
void Delete(int nId) EXCLUSIVE_LOCKS_REQUIRED(cs)
Delete an entry. It must not be in tried, and have refcount 0.
Definition: addrman.cpp:489
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Swap two elements in vRandom.
Definition: addrman.cpp:464
void Attempt(const CService &addr, bool fCountFailure, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1196
FastRandomContext insecure_rand
Source of random numbers for randomization in inner loops.
Definition: addrman_impl.h:164
void Good(const CService &addr, bool test_before_evict, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1188
void Clear() EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1255
void Unserialize(Stream &s_) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:247
std::set< int > m_tried_collisions
Holds addrs inserted into tried table that collide with existing entries.
Definition: addrman_impl.h:229
int nIdCount GUARDED_BY(cs)
last used nId
const std::vector< bool > m_asmap
Definition: addrman_impl.h:251
uint256 nKey
secret key to randomize bucket select with
Definition: addrman_impl.h:167
void ResolveCollisions() EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1204
AddrInfo * Create(const CAddress &addr, const CNetAddr &addrSource, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
find an entry, creating it if necessary.
Definition: addrman.cpp:449
std::vector< int > vRandom GUARDED_BY(cs)
randomly-ordered vector of all nIds This is mutable because it is unobservable outside the class,...
std::vector< CAddress > GetAddr_(size_t max_addresses, size_t max_pct, std::optional< Network > network) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:856
bool Add_(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:727
bool AddSingle(const CAddress &addr, const CNetAddr &source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs)
Attempt to add a single address to addrman's new table.
Definition: addrman.cpp:581
A CService with information about it as peer.
Definition: protocol.h:442
Network address.
Definition: netaddress.h:121
A combination of a network address (CNetAddr) and a (TCP) port.
Definition: netaddress.h:545
Fast randomness source.
Definition: random.h:156
256-bit opaque blob.
Definition: uint256.h:129
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
Network
A network type.
Definition: netaddress.h:44
ServiceFlags
nServices flags.
Definition: protocol.h:335
const char * source
Definition: rpcconsole.cpp:53
#define READWRITEAS(type, obj)
Definition: serialize.h:167
static Wrapper< Formatter, T & > Using(T &&t)
Cause serialization/deserialization of an object to be done using a specified formatter class.
Definition: serialize.h:574
#define READWRITE(...)
Definition: serialize.h:166
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
std::chrono::time_point< NodeClock, std::chrono::seconds > NodeSeconds
Definition: time.h:25