Bitcoin ABC  0.22.12
P2P Digital Currency
processor.h
Go to the documentation of this file.
1 // Copyright (c) 2018-2019 The Bitcoin 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_AVALANCHE_PROCESSOR_H
6 #define BITCOIN_AVALANCHE_PROCESSOR_H
7 
8 #include <avalanche/node.h>
9 #include <avalanche/protocol.h>
11 #include <eventloop.h>
12 #include <interfaces/chain.h>
13 #include <interfaces/handler.h>
14 #include <key.h>
15 #include <rwcollection.h>
16 
17 #include <boost/multi_index/composite_key.hpp>
18 #include <boost/multi_index/hashed_index.hpp>
19 #include <boost/multi_index/member.hpp>
20 #include <boost/multi_index/ordered_index.hpp>
21 #include <boost/multi_index_container.hpp>
22 
23 #include <atomic>
24 #include <chrono>
25 #include <cstdint>
26 #include <memory>
27 #include <vector>
28 
29 class Config;
30 class CBlockIndex;
31 class CScheduler;
32 
36 static constexpr bool AVALANCHE_DEFAULT_ENABLED = false;
37 
41 static constexpr int AVALANCHE_FINALIZATION_SCORE = 128;
42 
46 static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL = 16;
50 static constexpr size_t AVALANCHE_DEFAULT_COOLDOWN = 100;
54 static constexpr std::chrono::milliseconds AVALANCHE_DEFAULT_QUERY_TIMEOUT{
55  10000};
56 
60 static constexpr int AVALANCHE_MAX_INFLIGHT_POLL = 10;
61 
62 namespace avalanche {
63 
64 class Delegation;
65 class PeerManager;
66 class Proof;
67 
71 struct VoteRecord {
72 private:
73  // confidence's LSB bit is the result. Higher bits are actual confidence
74  // score.
75  uint16_t confidence = 0;
76 
77  // Historical record of votes.
78  uint8_t votes = 0;
79  // Each bit indicate if the vote is to be considered.
80  uint8_t consider = 0;
81  // How many in flight requests exists for this element.
82  mutable std::atomic<uint8_t> inflight{0};
83 
84  // Seed for pseudorandom operations.
85  const uint32_t seed = 0;
86 
87  // Track how many successful votes occured.
88  uint32_t successfulVotes = 0;
89 
90  // Track the nodes which are part of the quorum.
91  std::array<uint16_t, 8> nodeFilter{{0, 0, 0, 0, 0, 0, 0, 0}};
92 
93 public:
94  explicit VoteRecord(bool accepted) : confidence(accepted) {}
95 
99  VoteRecord(const VoteRecord &other)
100  : confidence(other.confidence), votes(other.votes),
101  consider(other.consider), inflight(other.inflight.load()),
102  successfulVotes(other.successfulVotes), nodeFilter(other.nodeFilter) {
103  }
104 
108  bool isAccepted() const { return confidence & 0x01; }
109 
110  uint16_t getConfidence() const { return confidence >> 1; }
111  bool hasFinalized() const {
113  }
114 
119  bool registerVote(NodeId nodeid, uint32_t error);
120 
126  bool registerPoll() const;
127 
132 
136  void clearInflightRequest(uint8_t count = 1) { inflight -= count; }
137 
138 private:
144  bool addNodeToQuorum(NodeId nodeid);
145 };
146 
147 class BlockUpdate {
148  union {
150  uintptr_t raw;
151  };
152 
153  static const size_t STATUS_BITS = 2;
154  static const uintptr_t MASK = (1 << STATUS_BITS) - 1;
155 
156  static_assert(
157  alignof(CBlockIndex) >= (1 << STATUS_BITS),
158  "CBlockIndex alignement doesn't allow for Status to be stored.");
159 
160 public:
161  enum Status : uint8_t {
166  };
167 
168  BlockUpdate(CBlockIndex *pindexIn, Status statusIn) : pindex(pindexIn) {
169  raw |= statusIn;
170  }
171 
172  Status getStatus() const { return Status(raw & MASK); }
173 
175  return reinterpret_cast<CBlockIndex *>(raw & ~MASK);
176  }
177 
178  const CBlockIndex *getBlockIndex() const {
179  return const_cast<BlockUpdate *>(this)->getBlockIndex();
180  }
181 };
182 
183 using BlockVoteMap =
184  std::map<const CBlockIndex *, VoteRecord, CBlockIndexWorkComparator>;
185 
186 struct query_timeout {};
187 
188 namespace {
189  struct AvalancheTest;
190 }
191 
192 class Processor {
194  std::chrono::milliseconds queryTimeoutDuration;
195 
200 
204  std::atomic<uint64_t> round;
205 
210  std::unique_ptr<PeerManager> peerManager GUARDED_BY(cs_peerManager);
211 
212  struct Query {
214  uint64_t round;
216 
223  mutable std::vector<CInv> invs;
224  };
225 
226  using QuerySet = boost::multi_index_container<
227  Query,
228  boost::multi_index::indexed_by<
229  // index by nodeid/round
230  boost::multi_index::hashed_unique<boost::multi_index::composite_key<
231  Query,
232  boost::multi_index::member<Query, NodeId, &Query::nodeid>,
233  boost::multi_index::member<Query, uint64_t, &Query::round>>>,
234  // sorted by timeout
235  boost::multi_index::ordered_non_unique<
236  boost::multi_index::tag<query_timeout>,
237  boost::multi_index::member<Query, TimePoint,
238  &Query::timeout>>>>;
239 
241 
243  struct PeerData;
244  std::unique_ptr<PeerData> peerData;
246 
249 
252  std::unique_ptr<interfaces::Handler> chainNotificationsHandler;
253 
254 public:
255  Processor(interfaces::Chain &chain, CConnman *connmanIn);
256  ~Processor();
257 
258  void setQueryTimeoutDuration(std::chrono::milliseconds d) {
259  queryTimeoutDuration = d;
260  }
261 
262  bool addBlockToReconcile(const CBlockIndex *pindex);
263  bool isAccepted(const CBlockIndex *pindex) const;
264  int getConfidence(const CBlockIndex *pindex) const;
265 
266  // TDOD: Refactor the API to remove the dependency on avalanche/protocol.h
267  void sendResponse(CNode *pfrom, Response response) const;
268  bool registerVotes(NodeId nodeid, const Response &response,
269  std::vector<BlockUpdate> &updates);
270 
271  bool addNode(NodeId nodeid, const Proof &proof,
272  const Delegation &delegation);
273  bool forNode(NodeId nodeid, std::function<bool(const Node &n)> func) const;
274 
275  CPubKey getSessionPubKey() const;
276  bool sendHello(CNode *pfrom) const;
277 
278  bool startEventLoop(CScheduler &scheduler);
279  bool stopEventLoop();
280 
281 private:
282  void runEventLoop();
283  void clearTimedoutRequests();
284  std::vector<CInv> getInvsForNextPoll(bool forPoll = true);
285  NodeId getSuitableNodeToQuery();
286 
287  friend struct ::avalanche::AvalancheTest;
288 };
289 
290 } // namespace avalanche
291 
295 extern std::unique_ptr<avalanche::Processor> g_avalanche;
296 
297 #endif // BITCOIN_AVALANCHE_PROCESSOR_H
uint32_t successfulVotes
Definition: processor.h:88
static constexpr bool AVALANCHE_DEFAULT_ENABLED
Is avalanche enabled by default.
Definition: processor.h:36
bool shouldPoll() const
Return if this item is in condition to be polled at the moment.
Definition: processor.h:131
boost::multi_index_container< Query, boost::multi_index::indexed_by< boost::multi_index::hashed_unique< boost::multi_index::composite_key< Query, boost::multi_index::member< Query, NodeId, &Query::nodeid >, boost::multi_index::member< Query, uint64_t, &Query::round > >>, boost::multi_index::ordered_non_unique< boost::multi_index::tag< query_timeout >, boost::multi_index::member< Query, TimePoint, &Query::timeout > >> > QuerySet
Definition: processor.h:238
std::vector< CInv > invs
We declare this as mutable so it can be modified in the multi_index.
Definition: processor.h:223
const CBlockIndex * getBlockIndex() const
Definition: processor.h:178
VoteRecord(bool accepted)
Definition: processor.h:94
std::atomic< uint8_t > inflight
Definition: processor.h:82
Status getStatus() const
Definition: processor.h:172
void setQueryTimeoutDuration(std::chrono::milliseconds d)
Definition: processor.h:258
std::unique_ptr< PeerData > peerData
Definition: processor.h:243
std::unique_ptr< interfaces::Handler > chainNotificationsHandler
Definition: processor.h:251
bool hasFinalized() const
Definition: processor.h:111
CBlockIndex * pindex
Definition: processor.h:149
bool registerVote(NodeId nodeid, uint32_t error)
Register a new vote for an item and update confidence accordingly.
Definition: processor.cpp:32
static constexpr std::chrono::milliseconds AVALANCHE_DEFAULT_QUERY_TIMEOUT
How long before we consider that a query timed out.
Definition: processor.h:54
static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
Definition: processor.h:46
CBlockIndex * getBlockIndex()
Definition: processor.h:174
Response response
Definition: processor.cpp:247
static constexpr int AVALANCHE_MAX_INFLIGHT_POLL
How many inflight requests can exist for one item.
Definition: processor.h:60
Definition: config.h:19
An encapsulated public key.
Definition: pubkey.h:31
RWCollection< QuerySet > queries
Definition: processor.h:240
std::chrono::milliseconds queryTimeoutDuration
Definition: processor.h:194
CConnman * connman
Definition: processor.h:193
const uint32_t seed
Definition: processor.h:85
int64_t NodeId
Definition: net.h:111
Definition: net.h:177
BlockUpdate(CBlockIndex *pindexIn, Status statusIn)
Definition: processor.h:168
static constexpr int AVALANCHE_FINALIZATION_SCORE
Finalization score.
Definition: processor.h:41
static constexpr size_t AVALANCHE_DEFAULT_COOLDOWN
Avalanche default cooldown in milliseconds.
Definition: processor.h:50
EventLoop eventLoop
Event loop machinery.
Definition: processor.h:248
RWCollection< BlockVoteMap > vote_records
Blocks to run avalanche on.
Definition: processor.h:199
Vote history.
Definition: processor.h:71
VoteRecord(const VoteRecord &other)
Copy semantic.
Definition: processor.h:99
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:105
The block chain is a tree shaped structure starting with the genesis block at the root...
Definition: blockindex.h:23
bool addNodeToQuorum(NodeId nodeid)
Add the node to the quorum.
Definition: processor.cpp:80
std::unique_ptr< avalanche::Processor > g_avalanche
Global avalanche instance.
Definition: processor.cpp:28
static int count
Definition: tests.c:35
#define GUARDED_BY(x)
Definition: threadsafety.h:45
std::chrono::time_point< std::chrono::steady_clock > TimePoint
Definition: node.h:17
uint16_t getConfidence() const
Definition: processor.h:110
void clearInflightRequest(uint8_t count=1)
Clear count inflight requests.
Definition: processor.h:136
An encapsulated secp256k1 private key.
Definition: key.h:25
Information about a peer.
Definition: net.h:818
bool registerPoll() const
Register that a request is being made regarding that item.
Definition: processor.cpp:111
Mutex cs_peerManager
Keep track of the peers and associated infos.
Definition: processor.h:209
std::atomic< uint64_t > round
Keep track of peers and queries sent.
Definition: processor.h:204
std::array< uint16_t, 8 > nodeFilter
Definition: processor.h:91
bool error(const char *fmt, const Args &... args)
Definition: system.h:47
std::map< const CBlockIndex *, VoteRecord, CBlockIndexWorkComparator > BlockVoteMap
Definition: processor.h:184
bool isAccepted() const
Vote accounting facilities.
Definition: processor.h:108