Bitcoin ABC 0.30.7
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 }
340 bool canShareLocalProof();
341
342 bool computeStakingReward(const CBlockIndex *pindex)
345 bool eraseStakingRewardWinner(const BlockHash &prevBlockHash)
347 void cleanupStakingRewards(const int minHeight)
350 const BlockHash &prevBlockHash,
351 std::vector<std::pair<ProofId, CScript>> &winners) const
353 bool getStakingRewardWinners(const BlockHash &prevBlockHash,
354 std::vector<CScript> &payouts) const
356 bool setStakingRewardWinners(const CBlockIndex *pprev,
357 const std::vector<CScript> &payouts)
359
360 // Implement NetEventInterface. Only FinalizeNode is of interest.
361 void InitializeNode(const ::Config &config, CNode &pnode,
362 ServiceFlags our_services) override {}
363 bool ProcessMessages(const ::Config &config, CNode *pnode,
364 std::atomic<bool> &interrupt) override {
365 return false;
366 }
367 bool SendMessages(const ::Config &config, CNode *pnode) override {
368 return false;
369 }
370
372 void FinalizeNode(const ::Config &config,
373 const CNode &node) override LOCKS_EXCLUDED(cs_main)
375
377 void addStakeContender(const ProofRef &proof)
379 int getStakeContenderStatus(const StakeContenderId &contenderId) const
381
386
387private:
388 void updatedBlockTip()
394 void runEventLoop()
398 std::vector<CInv> getInvsForNextPoll(bool forPoll = true)
400 bool sendHelloInternal(CNode *pfrom)
402 AnyVoteItem getVoteItemFromInv(const CInv &inv) const
404
408
417 100, 0.0000001};
418
431
434
435 IsWorthPolling(const Processor &_processor) : processor(_processor){};
436
437 bool operator()(const CBlockIndex *pindex) const
439 bool operator()(const ProofRef &proof) const
441 bool operator()(const CTransactionRef &tx) const;
442 };
443 bool isWorthPolling(const AnyVoteItem &item) const
445
448
449 GetLocalAcceptance(const Processor &_processor)
450 : processor(_processor){};
451
452 bool operator()(const CBlockIndex *pindex) const
454 bool operator()(const ProofRef &proof) const
456 bool operator()(const CTransactionRef &tx) const;
457 };
458 bool getLocalAcceptance(const AnyVoteItem &item) const {
459 return std::visit(GetLocalAcceptance(*this), item);
460 }
461
462 friend struct ::avalanche::AvalancheTest;
463};
464
465} // namespace avalanche
466
467#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:1278
Mutex cs_finalizedItems
Rolling bloom filter to track recently finalized inventory items of any type.
Definition: processor.h:428
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:1232
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:363
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:1119
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:1030
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:974
void runEventLoop() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:1125
bool isAvalancheServiceAvailable()
Definition: processor.h:321
Mutex cs_invalidatedBlocks
We don't need many blocks but a low false positive rate.
Definition: processor.h:415
void updatedBlockTip() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:1067
RWCollection< VoteMap > voteRecords
Items to run avalanche on.
Definition: processor.h:158
void setContenderStatusForLocalWinner(const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakeContenderCache
Helper to set the local winner in the contender cache.
Definition: processor.cpp:1053
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:996
bool getStakingRewardWinners(const BlockHash &prevBlockHash, std::vector< std::pair< ProofId, CScript > > &winners) const EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards)
Definition: processor.cpp:945
std::atomic< bool > m_canShareLocalProof
Definition: processor.h:215
void cleanupStakingRewards(const int minHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards
Definition: processor.cpp:926
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:1004
void InitializeNode(const ::Config &config, CNode &pnode, ServiceFlags our_services) override
Definition: processor.h:361
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:921
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:1363
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:367
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:429
int getStakeContenderStatus(const StakeContenderId &contenderId) const EXCLUSIVE_LOCKS_REQUIRED(!cs_stakeContenderCache
Definition: processor.cpp:1011
StakeContenderCache stakeContenderCache GUARDED_BY(cs_stakeContenderCache)
void clearTimedoutRequests() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:1193
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:458
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:263
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:1368
GetLocalAcceptance(const Processor &_processor)
Definition: processor.h:449
IsWorthPolling(const Processor &_processor)
Definition: processor.h:435
bool operator()(const CBlockIndex *pindex) const LOCKS_EXCLUDED(cs_main)
Definition: processor.cpp:1305
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