5#ifndef BITCOIN_AVALANCHE_PEERMANAGER_H
6#define BITCOIN_AVALANCHE_PEERMANAGER_H
20#include <boost/multi_index/composite_key.hpp>
21#include <boost/multi_index/hashed_index.hpp>
22#include <boost/multi_index/mem_fun.hpp>
23#include <boost/multi_index/member.hpp>
24#include <boost/multi_index/ordered_index.hpp>
25#include <boost/multi_index_container.hpp>
49 struct TestPeerManager;
59 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>>>>;
247 struct by_lastUpdate;
256 bmi::member<RemoteProof, ProofId, &RemoteProof::proofid>,
257 bmi::member<RemoteProof, NodeId, &RemoteProof::nodeid>>,
259 boost::hash<NodeId>>>,
261 bmi::hashed_non_unique<
262 bmi::tag<by_proofid>,
263 bmi::member<RemoteProof, ProofId, &RemoteProof::proofid>,
266 bmi::hashed_non_unique<
268 bmi::member<RemoteProof, NodeId, &RemoteProof::nodeid>>,
269 bmi::ordered_non_unique<
270 bmi::tag<by_lastUpdate>,
273 bmi::member<RemoteProof, NodeId, &RemoteProof::nodeid>,
333 template <
typename Callable>
335 auto it =
nodes.find(nodeid);
336 return it !=
nodes.end() && func(*it);
339 template <
typename Callable>
342 auto range = nview.equal_range(peer.
peerid);
343 for (
auto it = range.first; it != range.second; ++it) {
357 const std::chrono::seconds &nextTime);
407 return getProof(proofid) !=
nullptr;
411 std::unordered_set<ProofRef, SaltedProofHasher> ®isteredProofs);
413 template <
typename Callable>
415 auto &pview =
peers.get<by_proofid>();
416 auto it = pview.find(proofid);
417 return it != pview.end() && func(*it);
420 template <
typename Callable>
void forEachPeer(Callable &&func)
const {
421 for (
const auto &p :
peers) {
457 template <
typename Callable>
459 Callable &&getNodeAvailabilityScore) {
460 for (
auto it =
peers.begin(); it !=
peers.end(); it++) {
463 double peerScore{0.0};
465 peerScore += getNodeAvailabilityScore(
node.nodeid);
470 decayFactor * peerScore +
535 std::vector<std::pair<ProofId, CScript>> &winners);
540 std::unordered_set<ProofRef, SaltedProofHasher> ®isteredProofs);
543 template <
typename ProofContainer>
561 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
bool latchAvaproofsSent(NodeId nodeid)
Flag that a node did send its compact proofs.
bool registerProof(const ProofRef &proof, RegistrationMode mode=RegistrationMode::DEFAULT)
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)
const ProofRadixTree & getShareableProofsSnapshot() const
bool isBoundToPeer(const ProofId &proofid) const
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.
PeerManager(const Amount &stakeUtxoDustThresholdIn, ChainstateManager &chainmanIn, const ProofRef &localProofIn=ProofRef())
std::vector< Slot > slots
uint32_t totalPeersScore
Quorum management.
ProofPool danglingProofPool
void forEachPeer(Callable &&func) const
void setInvalid(const ProofId &proofid)
void forEachNode(const Peer &peer, Callable &&func) 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.
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)
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.
void updateAvailabilityScores(const double decayFactor, Callable &&getNodeAvailabilityScore)
auto getUnbroadcastProofs() const
bool isInConflictingPool(const ProofId &proofid) const
static constexpr int SELECT_NODE_MAX_RETRY
void cleanupDanglingProofs(std::unordered_set< ProofRef, SaltedProofHasher > ®isteredProofs)
ProofRef getProof(const ProofId &proofid) const
bool registerProof(const ProofRef &proof, ProofRegistrationState ®istrationState, RegistrationMode mode=RegistrationMode::DEFAULT)
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)
Map a proof to each utxo.
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.
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
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