5#ifndef BITCOIN_AVALANCHE_PEERMANAGER_H
6#define BITCOIN_AVALANCHE_PEERMANAGER_H
22#include <boost/multi_index/composite_key.hpp>
23#include <boost/multi_index/hashed_index.hpp>
24#include <boost/multi_index/mem_fun.hpp>
25#include <boost/multi_index/member.hpp>
26#include <boost/multi_index/ordered_index.hpp>
27#include <boost/multi_index_container.hpp>
51 struct TestPeerManager;
61 Slot(uint64_t startIn, uint32_t scoreIn,
PeerId peeridIn)
105 std::chrono::seconds nextPossibleConflictTime_)
160namespace bmi = boost::multi_index;
172 Peer, bmi::indexed_by<
174 bmi::hashed_unique<bmi::member<Peer, PeerId, &Peer::peerid>>,
176 bmi::hashed_unique<bmi::tag<by_proofid>,
proof_index,
179 bmi::ordered_non_unique<bmi::tag<by_score>,
score_index,
180 std::greater<uint32_t>>>>;
194 Node, bmi::indexed_by<
196 bmi::hashed_unique<bmi::member<Node, NodeId, &Node::nodeid>>,
198 bmi::ordered_non_unique<
199 bmi::tag<next_request_time>,
201 Node, bmi::member<Node, PeerId, &Node::peerid>,
217 bmi::hashed_non_unique<
218 bmi::tag<by_proofid>,
219 bmi::member<PendingNode, ProofId, &PendingNode::proofid>,
224 bmi::member<PendingNode, NodeId, &PendingNode::nodeid>>>>;
249 struct by_lastUpdate;
258 bmi::member<RemoteProof, ProofId, &RemoteProof::proofid>,
259 bmi::member<RemoteProof, NodeId, &RemoteProof::nodeid>>,
261 boost::hash<NodeId>>>,
263 bmi::hashed_non_unique<
264 bmi::tag<by_proofid>,
265 bmi::member<RemoteProof, ProofId, &RemoteProof::proofid>,
268 bmi::hashed_non_unique<
270 bmi::member<RemoteProof, NodeId, &RemoteProof::nodeid>>,
271 bmi::ordered_non_unique<
272 bmi::tag<by_lastUpdate>,
275 bmi::member<RemoteProof, NodeId, &RemoteProof::nodeid>,
338 template <
typename Callable>
340 auto it =
nodes.find(nodeid);
341 return it !=
nodes.end() && func(*it);
344 template <
typename Callable>
347 auto range = nview.equal_range(peer.
peerid);
348 for (
auto it = range.first; it != range.second; ++it) {
362 const std::chrono::seconds &nextTime);
412 return getProof(proofid) !=
nullptr;
416 std::unordered_set<ProofRef, SaltedProofHasher> ®isteredProofs);
418 template <
typename Callable>
420 auto &pview =
peers.get<by_proofid>();
421 auto it = pview.find(proofid);
422 return it != pview.end() && func(*it);
425 template <
typename Callable>
void forEachPeer(Callable &&func)
const {
426 for (
const auto &p :
peers) {
470 std::vector<std::pair<ProofId, CScript>> &newWinners);
475 const std::vector<std::pair<ProofId, CScript>> winners,
476 size_t maxPollable, std::vector<StakeContenderId> &pollableContenders);
478 const std::vector<CScript> &payoutScripts);
539 std::vector<std::pair<ProofId, CScript>> &winners);
544 std::unordered_set<ProofRef, SaltedProofHasher> ®isteredProofs);
547 template <
typename ProofContainer>
565 friend struct ::avalanche::TestPeerManager;
The block chain is a tree shaped structure starting with the genesis block at the root,...
RollingBloomFilter is a probabilistic "keep track of most recently inserted" set.
Simple class for background tasks that should be run periodically or once "after a while".
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Template for capturing information about block/transaction validation.
bool selectStakingRewardWinner(const CBlockIndex *pprev, std::vector< std::pair< ProofId, CScript > > &winners)
Deterministically select a list of payout scripts based on the proof set and the previous block hash.
uint32_t connectedPeersScore
boost::multi_index_container< PendingNode, bmi::indexed_by< bmi::hashed_non_unique< bmi::tag< by_proofid >, bmi::member< PendingNode, ProofId, &PendingNode::proofid >, SaltedProofIdHasher >, bmi::hashed_unique< bmi::tag< by_nodeid >, bmi::member< PendingNode, NodeId, &PendingNode::nodeid > > > > PendingNodeSet
std::vector< RemoteProof > getRemoteProofs(const NodeId nodeid) const
bool removeNode(NodeId nodeid)
bool setFinalized(PeerId peerid)
Latch on that this peer has a finalized proof.
bool dumpPeersToFile(const fs::path &dumpPath) const
RemoteProofSet remoteProofs
Remember which node sent which proof so we have an image of the proof set of our peers.
uint64_t getFragmentation() const
uint32_t getConnectedPeersScore() const
bool isDangling(const ProofId &proofid) const
bool updateNextRequestTime(NodeId nodeid, SteadyMilliseconds timeout)
bool unsetFlaky(const ProofId &proofid)
std::optional< bool > getRemotePresenceStatus(const ProofId &proofid) const
Get the presence remote status of a proof.
bool addNodeToPeer(const PeerSet::iterator &it)
bool shouldRequestMoreNodes()
Returns true if we encountered a lack of node since the last call.
bool exists(const ProofId &proofid) const
Return true if the (valid) proof exists, but only for non-dangling proofs.
bool isRemoteProof(const ProofId &proofid) const
size_t getNodeCount() const
PendingNodeSet pendingNodes
const ProofPool & getValidProofPool() const
bool verify() const
Perform consistency check on internal data structures.
bool forNode(NodeId nodeid, Callable &&func) const
bool forPeer(const ProofId &proofid, Callable &&func) const
boost::multi_index_container< Node, bmi::indexed_by< bmi::hashed_unique< bmi::member< Node, NodeId, &Node::nodeid > >, bmi::ordered_non_unique< bmi::tag< next_request_time >, bmi::composite_key< Node, bmi::member< Node, PeerId, &Node::peerid >, bmi::member< Node, SteadyMilliseconds, &Node::nextRequestTime > > > > > NodeSet
uint32_t getTotalPeersScore() const
void finalizeStakeContender(const StakeContenderId &contenderId, BlockHash &prevblockhash, std::vector< std::pair< ProofId, CScript > > &newWinners)
bool latchAvaproofsSent(NodeId nodeid)
Flag that a node did send its compact proofs.
bool registerProof(const ProofRef &proof, RegistrationMode mode=RegistrationMode::DEFAULT)
void cleanupStakeContenders(const int requestedMinHeight)
Make some of the contender cache API available.
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
uint64_t getSlotCount() const
static constexpr int SELECT_PEER_MAX_RETRY
ProofIdSet m_unbroadcast_proofids
Track proof ids to broadcast.
bool loadPeersFromFile(const fs::path &dumpPath, std::unordered_set< ProofRef, SaltedProofHasher > ®isteredProofs)
RejectionMode
Rejection mode.
void addUnbroadcastProof(const ProofId &proofid)
Proof broadcast API.
std::unordered_set< ProofRef, SaltedProofHasher > updatedBlockTip()
Update the peer set when a new block is connected.
void removeUnbroadcastProof(const ProofId &proofid)
PeerManager(const Amount &stakeUtxoDustThresholdIn, ChainstateManager &chainmanIn, bool stakingPreConsensus=false, const ProofRef &localProofIn=ProofRef())
void promoteStakeContendersToBlock(const CBlockIndex *pindex)
const ProofRadixTree & getShareableProofsSnapshot() const
bool isBoundToPeer(const ProofId &proofid) const
bool setContenderStatusForLocalWinners(const CBlockIndex *prevblock, const std::vector< std::pair< ProofId, CScript > > winners, size_t maxPollable, std::vector< StakeContenderId > &pollableContenders)
boost::multi_index_container< RemoteProof, bmi::indexed_by< bmi::hashed_unique< bmi::composite_key< RemoteProof, bmi::member< RemoteProof, ProofId, &RemoteProof::proofid >, bmi::member< RemoteProof, NodeId, &RemoteProof::nodeid > >, bmi::composite_key_hash< SaltedProofIdHasher, boost::hash< NodeId > > >, bmi::hashed_non_unique< bmi::tag< by_proofid >, bmi::member< RemoteProof, ProofId, &RemoteProof::proofid >, SaltedProofIdHasher >, bmi::hashed_non_unique< bmi::tag< by_nodeid >, bmi::member< RemoteProof, NodeId, &RemoteProof::nodeid > >, bmi::ordered_non_unique< bmi::tag< by_lastUpdate >, bmi::composite_key< RemoteProof, bmi::member< RemoteProof, NodeId, &RemoteProof::nodeid >, bmi::member< RemoteProof, std::chrono::seconds, &RemoteProof::lastUpdate > > > > > RemoteProofSet
size_t getPendingNodeCount() const
const ProofPool & getImmatureProofPool() const
ProofRadixTree shareableProofs
bool saveRemoteProof(const ProofId &proofid, const NodeId nodeid, const bool present)
CRollingBloomFilter invalidProofs
Filter for proofs that are consensus-invalid or were recently invalidated by avalanche (finalized rej...
uint64_t compact()
Trigger maintenance of internal data structures.
std::vector< Slot > slots
uint32_t totalPeersScore
Quorum management.
ProofPool danglingProofPool
void forEachPeer(Callable &&func) const
StakeContenderCache stakeContenderCache
void setInvalid(const ProofId &proofid)
void forEachNode(const Peer &peer, Callable &&func) const
int getStakeContenderStatus(const StakeContenderId &contenderId, BlockHash &prevblockhashout) const
const Amount & getStakeUtxoDustThreshold() const
void forEachFlakyProof(Callable &&func) const
bool isFlaky(const ProofId &proofid) const
ChainstateManager & chainman
bool isInvalid(const ProofId &proofid) const
std::unordered_set< ProofId, SaltedProofIdHasher > manualFlakyProofids
bool removePeer(const PeerId peerid)
Remove an existing peer.
const bool m_stakingPreConsensus
bool isImmature(const ProofId &proofid) const
bool addOrUpdateNode(const PeerSet::iterator &it, NodeId nodeid)
bool rejectProof(const ProofId &proofid, RejectionMode mode=RejectionMode::DEFAULT)
ProofPool immatureProofPool
Amount stakeUtxoDustThreshold
RegistrationMode
Registration mode.
ProofPool conflictingProofPool
const ProofPool & getConflictingProofPool() const
static constexpr size_t MAX_REMOTE_PROOFS
bool setFlaky(const ProofId &proofid)
void addStakeContender(const ProofRef &proof)
std::atomic< bool > needMoreNodes
Flag indicating that we failed to select a node and need to expand our node set.
PeerId selectPeer() const
Randomly select a peer to poll.
boost::multi_index_container< Peer, bmi::indexed_by< bmi::hashed_unique< bmi::member< Peer, PeerId, &Peer::peerid > >, bmi::hashed_unique< bmi::tag< by_proofid >, proof_index, SaltedProofIdHasher >, bmi::ordered_non_unique< bmi::tag< by_score >, score_index, std::greater< uint32_t > > > > PeerSet
Several nodes can make an avalanche peer.
auto getUnbroadcastProofs() const
bool isInConflictingPool(const ProofId &proofid) const
static constexpr int SELECT_NODE_MAX_RETRY
void cleanupDanglingProofs(std::unordered_set< ProofRef, SaltedProofHasher > ®isteredProofs)
void acceptStakeContender(const StakeContenderId &contenderId)
ProofRef getProof(const ProofId &proofid) const
bool registerProof(const ProofRef &proof, ProofRegistrationState ®istrationState, RegistrationMode mode=RegistrationMode::DEFAULT)
void rejectStakeContender(const StakeContenderId &contenderId)
bool removeNodeFromPeer(const PeerSet::iterator &it, uint32_t count=1)
bool updateNextPossibleConflictTime(PeerId peerid, const std::chrono::seconds &nextTime)
Proof and Peer related API.
void moveToConflictingPool(const ProofContainer &proofs)
bool setStakeContenderWinners(const CBlockIndex *pindex, const std::vector< CScript > &payoutScripts)
Map a proof to each utxo.
Cache to track stake contenders for recent blocks.
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
static constexpr uint32_t AVALANCHE_MAX_IMMATURE_PROOFS
Maximum number of immature proofs the peer manager will accept from the network.
std::unordered_set< ProofId, SaltedProofIdHasher > ProofIdSet
PeerId selectPeerImpl(const std::vector< Slot > &slots, const uint64_t slot, const uint64_t max)
Internal methods that are exposed for testing purposes.
RCUPtr< const Proof > ProofRef
Implement std::hash so RCUPtr can be used as a key for maps or sets.
A BlockHash is a unqiue identifier for a block.
SteadyMilliseconds nextRequestTime
std::chrono::seconds registration_time
std::chrono::seconds nextPossibleConflictTime
static constexpr auto DANGLING_TIMEOUT
Consider dropping the peer if no node is attached after this timeout expired.
const ProofId & getProofId() const
uint32_t getScore() const
Peer(PeerId peerid_, ProofRef proof_, std::chrono::seconds nextPossibleConflictTime_)
PendingNode(ProofId proofid_, NodeId nodeid_)
std::chrono::seconds lastUpdate
Slot(uint64_t startIn, uint32_t scoreIn, PeerId peeridIn)
Slot withPeerId(PeerId peeridIn) const
uint32_t getScore() const
bool follows(uint64_t slot) const
Slot withScore(uint64_t scoreIn) const
Slot withStart(uint64_t startIn) const
uint64_t getStart() const
bool precedes(uint64_t slot) const
bool contains(uint64_t slot) const
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
result_type operator()(const Peer &p) const
result_type operator()(const Peer &p) const
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
std::chrono::time_point< std::chrono::steady_clock, std::chrono::milliseconds > SteadyMilliseconds