33 auto it =
pview.find(proofid);
34 if (it ==
pview.end()) {
49 const PeerId peerid = it->peerid;
53 if (!
nodes.emplace(nodeid, peerid).second) {
58 if (!
nodes.modify(
nit, [&](
Node &n) { n.peerid = peerid; })) {
75 const ProofId &proofid = it->getProofId();
90 if (
p.node_count++ > 0) {
99 slots.emplace_back(start, score, it->peerid);
118 auto it =
nodes.find(nodeid);
119 if (it ==
nodes.end()) {
123 const PeerId peerid = it->peerid;
138 if (it ==
peers.end()) {
149 if (!
peers.modify(it, [&](
Peer &
p) { p.node_count = new_count; })) {
166 const size_t i = it->index;
171 if (i + 1 ==
slots.size()) {
184 auto it =
nodes.find(nodeid);
185 if (it ==
nodes.end()) {
193 auto it =
nodes.find(nodeid);
194 if (it ==
nodes.end()) {
198 return !it->avaproofsSent &&
208 auto it =
peers.find(peerid);
209 if (it ==
peers.end()) {
216 p.nextPossibleConflictTime =
217 std::max(
p.nextPossibleConflictTime,
nextTime);
220 return it->nextPossibleConflictTime ==
nextTime;
224 auto it =
peers.find(peerid);
225 if (it ==
peers.end()) {
230 peers.modify(it, [&](
Peer &
p) {
p.hasFinalized =
true; });
235template <
typename ProofContainer>
239 auto it =
peersView.find(proof->getId());
253 const ProofId &proofid = proof->getId();
256 const std::string &message) {
268 "proof-already-registered");
300 "utxo-missing-or-spent");
310 "-avalancheconflictingproofcooldown",
335 "cooldown-not-elapsed");
355 "conflicting-utxos");
372 "proof-already-registered");
446 auto it =
pview.find(proofid);
484 peer.node_count == 0 &&
518 "Proof dangling for too long (no connected node): %s\n",
519 proof->getId().GetHex());
542 if (it !=
nview.end() && it->peerid ==
p &&
561 for (
const auto &
p :
peers) {
570 "Invalidating proof %s: verification failed (%s)\n",
571 p.proof->getId().GetHex(), state.
ToString());
586 "Invalidating dangling proof %s: verification failed "
588 proof->getId().GetHex(), state.
ToString());
658 const bool present) {
668 while (
size_t(std::distance(begin, end)) >=
674 auto it =
remoteProofs.find(boost::make_tuple(proofid, nodeid));
685std::vector<RemoteProof>
692 for (
auto &it = begin; it != end; it++) {
701 return view.count(proofid) > 0;
705 auto it =
peers.find(peerid);
706 if (it ==
peers.end()) {
772 for (
auto it =
peers.begin(); it !=
peers.end(); it++) {
773 if (it->node_count == 0) {
779 if (!
peers.modify(it, [&](
Peer &
p) { p.index = i++; })) {
796 for (
size_t i = 0; i <
slots.size(); i++) {
813 if (it ==
peers.end() || it->index != i) {
829 std::unordered_set<COutPoint, SaltedOutpointHasher>
peersUtxos;
830 for (
const auto &
p :
peers) {
840 for (
const auto &
ss :
p.proof->getStakes()) {
841 const COutPoint &outpoint =
ss.getStake().getUTXO();
848 if (proof !=
p.proof) {
863 auto begin =
nview.lower_bound(
865 auto end =
nview.upper_bound(
868 for (
auto it = begin; it != end; ++it) {
880 if (
p.node_count == 0) {
886 if (
p.index >=
slots.size() ||
slots[
p.index].getPeerId() !=
p.peerid) {
891 if (
slots[
p.index].getScore() !=
p.getScore()) {
901 if (
p.node_count == 0 &&
931 size_t begin = 0, end = slots.size();
935 while ((end - begin) > 8) {
943 assert(begin <= i && i < end);
946 if (slots[i].contains(
slot)) {
947 return slots[i].getPeerId();
951 if (slots[i].precedes(
slot)) {
957 bottom = slots[begin].getStart();
962 if (slots[i].follows(
slot)) {
964 top = slots[end].getStart();
973 for (
size_t i = begin; i < end; i++) {
975 if (slots[i].contains(
slot)) {
976 return slots[i].getPeerId();
997 std::vector<std::pair<ProofId, CScript>> &winners) {
1011 std::chrono::duration_cast<std::chrono::seconds>(
1014 std::chrono::duration_cast<std::chrono::seconds>(
1039 if (!peer.hasFinalized ||
1046 return peer.getProofId() == proof->getId();
1057 "Staking reward hash has a suspicious value of zero for "
1058 "proof %s and blockhash %s, skipping\n",
1059 peer.getProofId().ToString(), prevblockhash.
ToString());
1114 winners.push_back({proof->getId(), proof->getPayoutScript()});
1120 winners.push_back({proof->getId(), proof->getPayoutScript()});
1153 std::unordered_map<PeerId, std::unordered_set<ProofId, SaltedProofIdHasher>>
1205 return std::nullopt;
1212 for (
auto it = begin; it != end; it++) {
1233 if (node_count == 0) {
1238 const double score =
double(
pit->getScore()) / node_count;
1252 bool present =
false;
1255 present =
pit->node_count > 0;
1262 const double score =
1275 return std::make_optional(
true);
1279 return std::make_optional(
false);
1282 return std::nullopt;
1298 file << peer.hasFinalized;
1299 file <<
int64_t(peer.registration_time.count());
1300 file <<
int64_t(peer.nextPossibleConflictTime.count());
1304 throw std::runtime_error(
strprintf(
"Failed to commit to file %s",
1310 throw std::runtime_error(
strprintf(
"Rename failed from %s to %s",
1314 }
catch (
const std::exception &
e) {
1335 "Failed to open avalanche peers file from disk.\n");
1345 "Unsupported avalanche peers file version.\n");
1358 int64_t nextPossibleConflictTime;
1361 file >> hasFinalized;
1363 file >> nextPossibleConflictTime;
1377 p.hasFinalized = hasFinalized;
1378 p.registration_time =
1380 p.nextPossibleConflictTime =
1381 std::chrono::seconds{nextPossibleConflictTime};
1387 }
catch (
const std::exception &
e) {
1389 "Failed to read the avalanche peers file data on disk: %s.\n",
static constexpr PeerId NO_PEER
static constexpr size_t AVALANCHE_DEFAULT_CONFLICTING_PROOF_COOLDOWN
Conflicting proofs cooldown time default value in seconds.
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
bool IsNull() const
Return true if the wrapped FILE* is nullptr, false otherwise.
FILE * Get() const
Get wrapped FILE* without transfer of ownership.
The block chain is a tree shaped structure starting with the genesis block at the root,...
int64_t GetBlockTime() const
BlockHash GetBlockHash() const
void insert(Span< const uint8_t > vKey)
bool contains(Span< const uint8_t > vKey) const
T * get()
Get allows to access the undelying pointer.
std::string ToString() const
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
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.
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 exists(const ProofId &proofid) const
Return true if the (valid) proof exists, but only for non-dangling proofs.
bool isRemoteProof(const ProofId &proofid) const
PendingNodeSet pendingNodes
bool verify() const
Perform consistency check on internal data structures.
bool forPeer(const ProofId &proofid, Callable &&func) const
bool latchAvaproofsSent(NodeId nodeid)
Flag that a node did send its compact proofs.
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
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)
bool isBoundToPeer(const ProofId &proofid) 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 setInvalid(const ProofId &proofid)
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
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.
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)
@ DUPLICATED
Already in pool.
@ REJECTED
Rejected due to conflicts.
@ SUCCEED
Added successfully.
AddProofStatus addProofIfPreferred(const ProofRef &proof, ConflictingProofSet &conflictingProofs)
Attempt to add a proof to the pool.
AddProofStatus addProofIfNoConflict(const ProofRef &proof, ConflictingProofSet &conflictingProofs)
Attempt to add a proof to the pool, and fail if there is a conflict on any UTXO.
size_t countProofs() const
bool removeProof(ProofId proofid)
void forEachProof(Callable &&func) const
ProofRef getProof(const ProofId &proofid) const
std::set< ProofRef, ConflictingProofComparator > ConflictingProofSet
ProofRef getLowestScoreProof() const
std::unordered_set< ProofRef, SaltedProofHasher > rescan(PeerManager &peerManager)
std::string ToString() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
static const uint256 ZERO
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
bool RenameOver(fs::path src, fs::path dest)
bool FileCommit(FILE *file)
Ensure file contents are fully committed to disk, using a platform-specific feature analogous to fsyn...
#define LogPrint(category,...)
static constexpr uint32_t AVALANCHE_MAX_IMMATURE_PROOFS
Maximum number of immature proofs the peer manager will accept from the network.
static bool isImmatureState(const ProofValidationState &state)
static constexpr uint64_t PEERS_DUMP_VERSION
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
FILE * fopen(const fs::path &p, const char *mode)
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
A BlockHash is a unqiue identifier for a block.
RCUPtr< T > remove(const KeyType &key)
Remove an element from the tree.
RCUPtr< T > get(const KeyType &key)
Get the value corresponding to a key.
bool forEachLeaf(Callable &&func) const
bool insert(const RCUPtr< T > &value)
Insert a value into the tree.
Facility for using an uint256 as a radix tree key.
SteadyMilliseconds nextRequestTime
static constexpr auto DANGLING_TIMEOUT
Consider dropping the peer if no node is attached after this timeout expired.
uint32_t getScore() const
uint64_t getStart() const
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define AssertLockHeld(cs)
#define NO_THREAD_SAFETY_ANALYSIS
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