Bitcoin ABC  0.29.2
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 
27 static constexpr int32_t ADDRMAN_TRIED_BUCKET_COUNT_LOG2{8};
28 static constexpr int ADDRMAN_TRIED_BUCKET_COUNT{
30 
32 static constexpr int32_t ADDRMAN_NEW_BUCKET_COUNT_LOG2{10};
33 static constexpr int ADDRMAN_NEW_BUCKET_COUNT{1
35 
37 static constexpr int32_t ADDRMAN_BUCKET_SIZE_LOG2{6};
38 static constexpr int ADDRMAN_BUCKET_SIZE{1 << ADDRMAN_BUCKET_SIZE_LOG2};
39 
43 class AddrInfo : public CAddress {
44 public:
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 
70  READWRITEAS(CAddress, obj);
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 
79  AddrInfo() : CAddress(), source() {}
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 = AdjustedTime()) const;
103 
106  double GetChance(NodeSeconds now = AdjustedTime()) const;
107 };
108 
109 class AddrManImpl {
110 public:
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 
159 private:
161  mutable Mutex cs;
162 
165 
168 
170  enum Format : uint8_t {
176  V2_ASMAP = 2,
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 
225  NodeSeconds m_last_good GUARDED_BY(cs);
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
double GetChance(NodeSeconds now=AdjustedTime()) const
Calculate the relative chance this entry should be given when selecting nodes to connect to.
Definition: addrman.cpp:119
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:66
bool IsTerrible(NodeSeconds now=AdjustedTime()) const
Determine whether the statistics about this entry are bad enough so that it can just be deleted.
Definition: addrman.cpp:88
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
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:79
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:506
std::pair< CAddress, NodeSeconds > Select(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1221
friend class AddrManCorrupted
Definition: addrman_impl.h:157
void Connected_(const CService &addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:902
void Attempt_(const CService &addr, bool fCountFailure, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:745
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:937
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:143
void Connected(const CService &addr, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1239
std::vector< CAddress > GetAddr(size_t max_addresses, size_t max_pct, std::optional< Network > network) const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1230
size_t size() const EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1174
std::vector< int > vRandom GUARDED_BY(cs)
randomly-ordered vector of all nIds This is mutable because it is unobservable outside the class,...
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:524
void SetServices(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1246
int vvTried[ADDRMAN_TRIED_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs)
list of "tried" buckets
AddrManImpl(std::vector< bool > &&asmap, int32_t consistency_check_ratio)
Definition: addrman.cpp:134
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:921
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:1253
void MakeDeterministic() EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1287
void Check() const EXCLUSIVE_LOCKS_REQUIRED(cs)
Consistency check, taking into account m_consistency_check_ratio.
Definition: addrman.cpp:1048
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:1066
bool Add(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1180
AddrInfo * Find(const CService &addr, int *pnId=nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs)
Find an entry.
Definition: addrman.cpp:434
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:1018
std::pair< CAddress, NodeSeconds > Select_(bool newOnly) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:766
std::pair< CAddress, NodeSeconds > SelectTriedCollision() EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1213
bool deterministic
Use deterministic bucket selection and inner loops randomization.
Definition: addrman_impl.h:255
std::unordered_map< CService, int, CServiceHash > mapAddr GUARDED_BY(cs)
find an nId based on its network address and port.
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:667
int vvNew[ADDRMAN_NEW_BUCKET_COUNT][ADDRMAN_BUCKET_SIZE] GUARDED_BY(cs)
list of "new" buckets
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:491
void SwapRandom(unsigned int nRandomPos1, unsigned int nRandomPos2) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Swap two elements in vRandom.
Definition: addrman.cpp:466
void Attempt(const CService &addr, bool fCountFailure, NodeSeconds time) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1198
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:1190
void Clear() EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:1257
void Unserialize(Stream &s_) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: addrman.cpp:249
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:1206
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:451
std::vector< CAddress > GetAddr_(size_t max_addresses, size_t max_pct, std::optional< Network > network) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:858
std::unordered_map< int, AddrInfo > mapInfo GUARDED_BY(cs)
table with information about all nIds
bool Add_(const std::vector< CAddress > &vAddr, const CNetAddr &source, std::chrono::seconds time_penalty) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: addrman.cpp:729
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:583
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:257
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
NodeSeconds AdjustedTime()
Definition: timedata.h:70