Bitcoin ABC 0.30.5
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/config.h>
9#include <avalanche/node.h>
10#include <avalanche/proof.h>
12#include <avalanche/protocol.h>
14#include <avalanche/voterecord.h> // For AVALANCHE_MAX_INFLIGHT_POLL
15#include <blockindex.h>
17#include <common/bloom.h>
18#include <eventloop.h>
19#include <interfaces/chain.h>
20#include <interfaces/handler.h>
21#include <key.h>
22#include <net.h>
24#include <rwcollection.h>
25#include <util/variant.h>
26#include <validationinterface.h>
27
28#include <boost/multi_index/composite_key.hpp>
29#include <boost/multi_index/hashed_index.hpp>
30#include <boost/multi_index/member.hpp>
31#include <boost/multi_index/ordered_index.hpp>
32#include <boost/multi_index_container.hpp>
33
34#include <atomic>
35#include <chrono>
36#include <cstdint>
37#include <memory>
38#include <unordered_map>
39#include <variant>
40#include <vector>
41
42class ArgsManager;
43class CConnman;
44class CNode;
45class CScheduler;
46class Config;
47class PeerManager;
48struct bilingual_str;
49
53static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL = 16;
54
58static constexpr std::chrono::milliseconds AVALANCHE_DEFAULT_QUERY_TIMEOUT{
59 10000};
60
71
72namespace avalanche {
73
74class Delegation;
75class PeerManager;
76class ProofRegistrationState;
77struct VoteRecord;
78
79enum struct VoteStatus : uint8_t {
80 Invalid,
84 Stale,
85};
86
88 std::variant<const ProofRef, const CBlockIndex *, const CTransactionRef>;
89
93
94public:
96 : item(std::move(itemIn)), status(statusIn) {}
97
98 const VoteStatus &getStatus() const { return status; }
99 const AnyVoteItem &getVoteItem() const { return item; }
100};
101
103 bool operator()(const AnyVoteItem &lhs, const AnyVoteItem &rhs) const {
104 // If the variants are of different types, sort them by variant index
105 if (lhs.index() != rhs.index()) {
106 return lhs.index() < rhs.index();
107 }
108
109 return std::visit(
111 [](const ProofRef &lhs, const ProofRef &rhs) {
112 return ProofComparatorByScore()(lhs, rhs);
113 },
114 [](const CBlockIndex *lhs, const CBlockIndex *rhs) {
115 // Reverse ordering so we get the highest work first
116 return CBlockIndexWorkComparator()(rhs, lhs);
117 },
118 [](const CTransactionRef &lhs, const CTransactionRef &rhs) {
119 return lhs->GetId() < rhs->GetId();
120 },
121 [](const auto &lhs, const auto &rhs) {
122 // This serves 2 purposes:
123 // - This makes sure that we don't forget to implement a
124 // comparison case when adding a new variant type.
125 // - This avoids having to write all the cross type cases
126 // which are already handled by the index sort above.
127 // Because the compiler has no way to determine that, we
128 // cannot use static assertions here without having to
129 // define the whole type matrix also.
130 assert(false);
131 // Return any bool, it's only there to make the compiler
132 // happy.
133 return false;
134 },
135 },
136 lhs, rhs);
137 }
138};
139using VoteMap = std::map<AnyVoteItem, VoteRecord, VoteMapComparator>;
140
142
143namespace {
144 struct AvalancheTest;
145}
146
147// FIXME Implement a proper notification handler for node disconnection instead
148// of implementing the whole NetEventsInterface for a single interesting event.
149class Processor final : public NetEventsInterface {
154
159
163 std::atomic<uint64_t> round;
164
169 std::unique_ptr<PeerManager> peerManager GUARDED_BY(cs_peerManager);
170
171 struct Query {
173 uint64_t round;
175
182 mutable std::vector<CInv> invs;
183 };
184
185 using QuerySet = boost::multi_index_container<
186 Query,
187 boost::multi_index::indexed_by<
188 // index by nodeid/round
189 boost::multi_index::hashed_unique<boost::multi_index::composite_key<
190 Query,
191 boost::multi_index::member<Query, NodeId, &Query::nodeid>,
192 boost::multi_index::member<Query, uint64_t, &Query::round>>>,
193 // sorted by timeout
194 boost::multi_index::ordered_non_unique<
195 boost::multi_index::tag<query_timeout>,
196 boost::multi_index::member<Query, SteadyMilliseconds,
197 &Query::timeout>>>>;
198
200
202 struct PeerData;
203 std::unique_ptr<PeerData> peerData;
205
208
214 std::atomic<bool> quorumIsEstablished{false};
215 std::atomic<bool> m_canShareLocalProof{false};
217 std::atomic<int64_t> avaproofsNodeCounter{0};
218
220 const uint32_t staleVoteThreshold;
221 const uint32_t staleVoteFactor;
222
225 std::unique_ptr<interfaces::Handler> chainNotificationsHandler;
226
228 const CBlockIndex *finalizationTip GUARDED_BY(cs_finalizationTip){nullptr};
229
235 std::unordered_set<NodeId>
236 delayedAvahelloNodeIds GUARDED_BY(cs_delayedAvahelloNodeIds);
237
240 // Ordered list of acceptable winners, only the first is used for mining
241 std::vector<std::pair<ProofId, CScript>> winners;
242 };
243
245 std::unordered_map<BlockHash, StakingReward, SaltedUint256Hasher>
247
250
253 CScheduler &scheduler, std::unique_ptr<PeerData> peerDataIn,
254 CKey sessionKeyIn, uint32_t minQuorumTotalScoreIn,
255 double minQuorumConnectedScoreRatioIn,
256 int64_t minAvaproofsNodeCountIn, uint32_t staleVoteThresholdIn,
257 uint32_t staleVoteFactorIn, Amount stakeUtxoDustThresholdIn,
258 bool preConsensus, bool stakingPreConsensus);
259
260public:
261 const bool m_preConsensus{false};
262 const bool m_stakingPreConsensus{false};
263
264 ~Processor();
265
266 static std::unique_ptr<Processor>
267 MakeProcessor(const ArgsManager &argsman, interfaces::Chain &chain,
269 CTxMemPool *mempoolIn, CScheduler &scheduler,
271
272 bool addToReconcile(const AnyVoteItem &item)
279 bool reconcileOrFinalize(const ProofRef &proof)
281 bool isAccepted(const AnyVoteItem &item) const;
282 int getConfidence(const AnyVoteItem &item) const;
283
284 bool isRecentlyFinalized(const uint256 &itemId) const
287
288 // TODO: Refactor the API to remove the dependency on avalanche/protocol.h
289 void sendResponse(CNode *pfrom, Response response) const;
290 bool registerVotes(NodeId nodeid, const Response &response,
291 std::vector<VoteItemUpdate> &updates, int &banscore,
292 std::string &error)
295
296 template <typename Callable>
297 auto withPeerManager(Callable &&func) const
300 return func(*peerManager);
301 }
302
310 bool sendHello(CNode *pfrom)
314
315 ProofRef getLocalProof() const;
317
318 /*
319 * Return whether the avalanche service flag should be set.
320 */
322
326 return finalizationTip != nullptr;
327 }
328
329 bool startEventLoop(CScheduler &scheduler);
330 bool stopEventLoop();
331
334 int64_t getAvaproofsNodeCounter() const {
335 return avaproofsNodeCounter.load();
336 }
339 bool canShareLocalProof();
340
341 bool computeStakingReward(const CBlockIndex *pindex)
343 bool eraseStakingRewardWinner(const BlockHash &prevBlockHash)
345 void cleanupStakingRewards(const int minHeight)
348 const BlockHash &prevBlockHash,
349 std::vector<std::pair<ProofId, CScript>> &winners) const
351 bool getStakingRewardWinners(const BlockHash &prevBlockHash,
352 std::vector<CScript> &payouts) const
354 bool setStakingRewardWinners(const CBlockIndex *pprev,
355 const std::vector<CScript> &payouts)
357
358 // Implement NetEventInterface. Only FinalizeNode is of interest.
359 void InitializeNode(const ::Config &config, CNode &pnode,
360 ServiceFlags our_services) override {}
361 bool ProcessMessages(const ::Config &config, CNode *pnode,
362 std::atomic<bool> &interrupt) override {
363 return false;
364 }
365 bool SendMessages(const ::Config &config, CNode *pnode) override {
366 return false;
367 }
368
370 void FinalizeNode(const ::Config &config,
371 const CNode &node) override LOCKS_EXCLUDED(cs_main)
373
375 void addStakeContender(const ProofRef &proof)
377 int getStakeContenderStatus(const StakeContenderId &contenderId) const
379
384
385private:
386 void updatedBlockTip()
391 void runEventLoop()
395 std::vector<CInv> getInvsForNextPoll(bool forPoll = true)
397 bool sendHelloInternal(CNode *pfrom)
399 AnyVoteItem getVoteItemFromInv(const CInv &inv) const
401
410 100, 0.0000001};
411
424
427
428 IsWorthPolling(const Processor &_processor) : processor(_processor){};
429
430 bool operator()(const CBlockIndex *pindex) const
432 bool operator()(const ProofRef &proof) const
434 bool operator()(const CTransactionRef &tx) const;
435 };
436 bool isWorthPolling(const AnyVoteItem &item) const
438
441
442 GetLocalAcceptance(const Processor &_processor)
443 : processor(_processor){};
444
445 bool operator()(const CBlockIndex *pindex) const
447 bool operator()(const ProofRef &proof) const
449 bool operator()(const CTransactionRef &tx) const;
450 };
451 bool getLocalAcceptance(const AnyVoteItem &item) const {
452 return std::visit(GetLocalAcceptance(*this), item);
453 }
454
455 friend struct ::avalanche::AvalancheTest;
456};
457
458} // namespace avalanche
459
460#endif // BITCOIN_AVALANCHE_PROCESSOR_H
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:25
Definition: net.h:856
Inv(ventory) message data.
Definition: protocol.h:581
An encapsulated secp256k1 private key.
Definition: key.h:28
Information about a peer.
Definition: net.h:460
An encapsulated public key.
Definition: pubkey.h:31
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Definition: bloom.h:115
Simple class for background tasks that should be run periodically or once "after a while".
Definition: scheduler.h:41
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:212
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1219
Definition: config.h:19
Interface for message handling.
Definition: net.h:805
void sendResponse(CNode *pfrom, Response response) const
Definition: processor.cpp:520
const uint32_t staleVoteThreshold
Voting parameters.
Definition: processor.h:220
std::atomic< bool > quorumIsEstablished
Definition: processor.h:214
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, SteadyMilliseconds, &Query::timeout > > > > QuerySet
Definition: processor.h:197
AnyVoteItem getVoteItemFromInv(const CInv &inv) const EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:1248
Mutex cs_finalizedItems
Rolling bloom filter to track recently finalized inventory items of any type.
Definition: processor.h:421
bool sendHelloInternal(CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(cs_delayedAvahelloNodeIds)
Definition: processor.cpp:691
int getConfidence(const AnyVoteItem &item) const
Definition: processor.cpp:468
bool addToReconcile(const AnyVoteItem &item) EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:417
std::vector< CInv > getInvsForNextPoll(bool forPoll=true) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:1202
int64_t getAvaproofsNodeCounter() const
Definition: processor.h:334
RWCollection< QuerySet > queries
Definition: processor.h:199
bool hasFinalizedTip() const EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizationTip)
Whether there is a finalized tip.
Definition: processor.h:324
bool ProcessMessages(const ::Config &config, CNode *pnode, std::atomic< bool > &interrupt) override
Definition: processor.h:361
Mutex cs_stakeContenderCache
Definition: processor.h:248
bool registerVotes(NodeId nodeid, const Response &response, std::vector< VoteItemUpdate > &updates, int &banscore, std::string &error) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:527
void transactionAddedToMempool(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:1089
const CBlockIndex *finalizationTip GUARDED_BY(cs_finalizationTip)
Definition: processor.h:228
bool sendHello(CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
Send a avahello message.
Definition: processor.cpp:726
bool isRecentlyFinalized(const uint256 &itemId) const EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:482
bool startEventLoop(CScheduler &scheduler)
Definition: processor.cpp:758
bool isQuorumEstablished() LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:788
void promoteStakeContendersToTip() EXCLUSIVE_LOCKS_REQUIRED(!cs_stakeContenderCache
Promote stake contender cache entries to the latest chain tip.
Definition: processor.cpp:1020
std::atomic< uint64_t > round
Keep track of peers and queries sent.
Definition: processor.h:163
static std::unique_ptr< Processor > MakeProcessor(const ArgsManager &argsman, interfaces::Chain &chain, CConnman *connman, ChainstateManager &chainman, CTxMemPool *mempoolIn, CScheduler &scheduler, bilingual_str &error)
Definition: processor.cpp:219
EventLoop eventLoop
Event loop machinery.
Definition: processor.h:207
CTxMemPool * mempool
Definition: processor.h:153
int64_t minAvaproofsNodeCount
Definition: processor.h:216
const bool m_preConsensus
Definition: processor.h:261
Mutex cs_delayedAvahelloNodeIds
Definition: processor.h:230
bool setStakingRewardWinners(const CBlockIndex *pprev, const std::vector< CScript > &payouts) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards
Definition: processor.cpp:964
void runEventLoop() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:1095
bool isAvalancheServiceAvailable()
Definition: processor.h:321
Mutex cs_invalidatedBlocks
We don't need many blocks but a low false positive rate.
Definition: processor.h:408
void updatedBlockTip() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:1037
RWCollection< VoteMap > voteRecords
Items to run avalanche on.
Definition: processor.h:158
std::unique_ptr< interfaces::Handler > chainNotificationsHandler
Definition: processor.h:225
uint32_t minQuorumScore
Quorum management.
Definition: processor.h:212
void FinalizeNode(const ::Config &config, const CNode &node) override LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Handle removal of a node.
Definition: processor.cpp:986
bool getStakingRewardWinners(const BlockHash &prevBlockHash, std::vector< std::pair< ProofId, CScript > > &winners) const EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards)
Definition: processor.cpp:935
std::atomic< bool > m_canShareLocalProof
Definition: processor.h:215
void cleanupStakingRewards(const int minHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards
Definition: processor.cpp:918
bool isAccepted(const AnyVoteItem &item) const
Definition: processor.cpp:454
ProofRef getLocalProof() const
Definition: processor.cpp:748
void addStakeContender(const ProofRef &proof) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Track votes on stake contenders.
Definition: processor.cpp:994
void InitializeNode(const ::Config &config, CNode &pnode, ServiceFlags our_services) override
Definition: processor.h:359
bool reconcileOrFinalize(const ProofRef &proof) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Wrapper around the addToReconcile for proofs that adds back the finalization flag to the peer if it i...
Definition: processor.cpp:435
const uint32_t staleVoteFactor
Definition: processor.h:221
void sendDelayedAvahello() EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
Definition: processor.cpp:731
std::unique_ptr< PeerData > peerData
Definition: processor.h:203
bool eraseStakingRewardWinner(const BlockHash &prevBlockHash) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards)
Definition: processor.cpp:913
const bool m_stakingPreConsensus
Definition: processor.h:262
CConnman * connman
Definition: processor.h:151
bool isWorthPolling(const AnyVoteItem &item) const EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:1333
CPubKey getSessionPubKey() const
Definition: processor.cpp:687
auto withPeerManager(Callable &&func) const EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.h:297
std::unique_ptr< PeerManager > peerManager GUARDED_BY(cs_peerManager)
Processor(Config avaconfig, interfaces::Chain &chain, CConnman *connmanIn, ChainstateManager &chainman, CTxMemPool *mempoolIn, CScheduler &scheduler, std::unique_ptr< PeerData > peerDataIn, CKey sessionKeyIn, uint32_t minQuorumTotalScoreIn, double minQuorumConnectedScoreRatioIn, int64_t minAvaproofsNodeCountIn, uint32_t staleVoteThresholdIn, uint32_t staleVoteFactorIn, Amount stakeUtxoDustThresholdIn, bool preConsensus, bool stakingPreConsensus)
Definition: processor.cpp:142
ChainstateManager & chainman
Definition: processor.h:152
std::atomic< int64_t > avaproofsNodeCounter
Definition: processor.h:217
bool SendMessages(const ::Config &config, CNode *pnode) override
Definition: processor.h:365
bool computeStakingReward(const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:881
ProofRegistrationState getLocalProofRegistrationState() const
Definition: processor.cpp:752
CRollingBloomFilter finalizedItems GUARDED_BY(cs_finalizedItems)
Definition: processor.h:422
int getStakeContenderStatus(const StakeContenderId &contenderId) const EXCLUSIVE_LOCKS_REQUIRED(!cs_stakeContenderCache
Definition: processor.cpp:1001
StakeContenderCache stakeContenderCache GUARDED_BY(cs_stakeContenderCache)
void clearTimedoutRequests() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:1163
std::unordered_map< BlockHash, StakingReward, SaltedUint256Hasher > stakingRewards GUARDED_BY(cs_stakingRewards)
Mutex cs_peerManager
Keep track of the peers and associated infos.
Definition: processor.h:168
bool getLocalAcceptance(const AnyVoteItem &item) const
Definition: processor.h:451
std::unordered_set< NodeId > delayedAvahelloNodeIds GUARDED_BY(cs_delayedAvahelloNodeIds)
A list of the nodes that did not get our proof announced via avahello yet because we had no inbound c...
void avaproofsSent(NodeId nodeid) LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:767
double minQuorumConnectedScoreRatio
Definition: processor.h:213
void clearFinalizedItems() EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:486
Cache to track stake contenders for recent blocks.
const AnyVoteItem & getVoteItem() const
Definition: processor.h:99
VoteItemUpdate(AnyVoteItem itemIn, VoteStatus statusIn)
Definition: processor.h:95
const VoteStatus & getStatus() const
Definition: processor.h:98
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:123
256-bit opaque blob.
Definition: uint256.h:129
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
bool error(const char *fmt, const Args &...args)
Definition: logging.h:226
std::map< AnyVoteItem, VoteRecord, VoteMapComparator > VoteMap
Definition: processor.h:139
std::variant< const ProofRef, const CBlockIndex *, const CTransactionRef > AnyVoteItem
Definition: processor.h:88
Definition: init.h:28
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
int64_t NodeId
Definition: nodeid.h:10
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
Response response
Definition: processor.cpp:497
static constexpr std::chrono::milliseconds AVALANCHE_DEFAULT_QUERY_TIMEOUT
How long before we consider that a query timed out.
Definition: processor.h:58
static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
Definition: processor.h:53
static constexpr uint32_t AVALANCHE_FINALIZED_ITEMS_FILTER_NUM_ELEMENTS
The size of the finalized items filter.
Definition: processor.h:69
ServiceFlags
nServices flags.
Definition: protocol.h:335
Definition: amount.h:19
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
bool operator()(const CBlockIndex *pindex) const LOCKS_EXCLUDED(cs_main)
Definition: processor.cpp:1338
GetLocalAcceptance(const Processor &_processor)
Definition: processor.h:442
IsWorthPolling(const Processor &_processor)
Definition: processor.h:428
bool operator()(const CBlockIndex *pindex) const LOCKS_EXCLUDED(cs_main)
Definition: processor.cpp:1275
SteadyMilliseconds timeout
Definition: processor.h:174
std::vector< CInv > invs
We declare this as mutable so it can be modified in the multi_index.
Definition: processor.h:182
std::vector< std::pair< ProofId, CScript > > winners
Definition: processor.h:241
Compare proofs by score, then by id in case of equality.
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
bool operator()(const AnyVoteItem &lhs, const AnyVoteItem &rhs) const
Definition: processor.h:103
Bilingual messages:
Definition: translation.h:17
#define LOCK(cs)
Definition: sync.h:306
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
#define LOCKS_EXCLUDED(...)
Definition: threadsafety.h:55
std::chrono::time_point< std::chrono::steady_clock, std::chrono::milliseconds > SteadyMilliseconds
Definition: time.h:31
assert(!tx.IsCoinBase())
static constexpr int AVALANCHE_MAX_INFLIGHT_POLL
How many inflight requests can exist for one item.
Definition: voterecord.h:40