34 size_t max_elements) {
35 auto &pview =
peers.get<by_proofid>();
36 auto it = pview.find(proofid);
37 if (it == pview.end()) {
50 size_t max_elements) {
53 const PeerId peerid = it->peerid;
55 auto nit =
nodes.find(nodeid);
56 if (nit ==
nodes.end()) {
57 if (!
nodes.emplace(nodeid, peerid, max_elements).second) {
61 const PeerId oldpeerid = nit->peerid;
62 if (!
nodes.modify(nit, [&](
Node &n) { n.peerid = peerid; })) {
79 const ProofId &proofid = it->getProofId();
101 const uint32_t score = p.
getScore();
103 slots.emplace_back(start, score, it->peerid);
120 auto it =
nodes.find(nodeid);
121 if (it ==
nodes.end()) {
125 const PeerId peerid = it->peerid;
140 if (it ==
peers.end()) {
144 assert(count <= it->node_count);
150 const uint32_t new_count = it->node_count -
count;
151 if (!
peers.modify(it, [&](
Peer &p) { p.node_count = new_count; })) {
168 const size_t i = it->index;
173 if (i + 1 ==
slots.size()) {
187 auto it =
nodes.find(nodeid);
188 if (it ==
nodes.end()) {
200 auto it =
nodes.find(nodeid);
201 if (it ==
nodes.end()) {
205 if (it->last_round >
response.getRound()) {
210 auto timeout = Now<SteadyMilliseconds>() +
211 std::chrono::milliseconds(
response.getCooldown());
220 auto it =
nodes.find(nodeid);
221 if (it ==
nodes.end()) {
225 return !it->avaproofsSent &&
234 PeerId peerid,
const std::chrono::seconds &nextTime) {
235 auto it =
peers.find(peerid);
236 if (it ==
peers.end()) {
247 return it->nextPossibleConflictTime == nextTime;
251 auto it =
peers.find(peerid);
252 if (it ==
peers.end()) {
262template <
typename ProofContainer>
264 auto &peersView =
peers.get<by_proofid>();
265 for (
const ProofRef &proof : proofs) {
266 auto it = peersView.find(proof->getId());
267 if (it != peersView.end()) {
280 const ProofId &proofid = proof->getId();
283 const std::string &message) {
284 return registrationState.
Invalid(
295 "proof-already-registered");
327 "utxo-missing-or-spent");
334 auto now = GetTime<std::chrono::seconds>();
335 auto nextCooldownTimePoint =
337 "-avalancheconflictingproofcooldown",
342 case ProofPool::AddProofStatus::REJECTED: {
344 auto bestPossibleConflictTime = std::chrono::seconds(0);
345 auto &pview =
peers.get<by_proofid>();
346 for (
auto &conflictingProof : conflictingProofs) {
347 auto it = pview.find(conflictingProof->getId());
348 assert(it != pview.end());
351 bestPossibleConflictTime = std::max(
352 bestPossibleConflictTime, it->nextPossibleConflictTime);
355 nextCooldownTimePoint);
358 if (bestPossibleConflictTime > now) {
362 "cooldown-not-elapsed");
378 ProofPool::AddProofStatus::REJECTED
382 "conflicting-utxos");
392 assert(status == ProofPool::AddProofStatus::SUCCEED);
396 case ProofPool::AddProofStatus::DUPLICATED:
399 "proof-already-registered");
400 case ProofPool::AddProofStatus::SUCCEED:
413 const ProofId &conflictingProofId = conflicting->getId();
416 "Evicted dangling proof %s due to conflict with peer proof "
425 auto inserted =
peers.emplace(peerid, proof, nextCooldownTimePoint);
439 auto &pendingNodesView =
pendingNodes.get<by_proofid>();
440 auto range = pendingNodesView.equal_range(proofid);
445 std::vector<std::pair<NodeId, size_t>> nodeids_and_max_elements;
446 nodeids_and_max_elements.reserve(std::distance(range.first, range.second));
447 std::transform(range.first, range.second,
448 std::back_inserter(nodeids_and_max_elements),
450 return std::make_pair(n.nodeid, n.max_elements);
453 for (
const auto &[nodeid, max_elements] : nodeids_and_max_elements) {
490 auto &pview =
peers.get<by_proofid>();
491 auto it = pview.find(proofid);
492 assert(it != pview.end());
504 if (!conflictingProof) {
520 std::unordered_set<ProofRef, SaltedProofHasher> ®isteredProofs) {
521 registeredProofs.clear();
522 const auto now = GetTime<std::chrono::seconds>();
524 std::vector<ProofRef> newlyDanglingProofs;
529 peer.node_count == 0 &&
536 newlyDanglingProofs.push_back(peer.proof);
543 std::vector<ProofRef> previouslyDanglingProofs;
546 previouslyDanglingProofs.push_back(proof);
549 for (
const ProofRef &proof : previouslyDanglingProofs) {
552 registeredProofs.insert(proof);
556 for (
const ProofRef &proof : newlyDanglingProofs) {
573 "Proof dangling for too long (no connected node): %s\n",
574 proof->getId().GetHex());
597 if (it != nview.end() && it->peerid == p &&
598 it->nextRequestTime <= Now<SteadyMilliseconds>()) {
610 std::vector<ProofId> invalidProofIds;
611 std::vector<ProofRef> newImmatures;
616 for (
const auto &p :
peers) {
620 newImmatures.push_back(p.proof);
622 invalidProofIds.push_back(p.getProofId());
625 "Invalidating proof %s: verification failed (%s)\n",
626 p.proof->getId().GetHex(), state.
ToString());
637 invalidProofIds.push_back(proof->getId());
641 "Invalidating dangling proof %s: verification failed "
643 proof->getId().GetHex(), state.
ToString());
651 for (
const ProofId &invalidProofId : invalidProofIds) {
657 for (
auto &p : newImmatures) {
661 return registeredProofs;
684 auto &pview =
peers.get<by_proofid>();
685 return pview.find(proofid) != pview.end();
713 const bool present) {
728 auto &remoteProofsByLastUpdate =
remoteProofs.get<by_lastUpdate>();
729 auto [begin, end] = remoteProofsByLastUpdate.equal_range(nodeid);
736 while (
size_t(std::distance(begin, end)) >=
739 begin = remoteProofsByLastUpdate.erase(begin);
742 auto it =
remoteProofs.find(boost::make_tuple(proofid, nodeid));
748 .emplace(
RemoteProof{proofid, nodeid, GetTime<std::chrono::seconds>(),
753std::vector<RemoteProof>
755 std::vector<RemoteProof> nodeRemoteProofs;
757 auto &remoteProofsByLastUpdate =
remoteProofs.get<by_lastUpdate>();
758 auto [begin, end] = remoteProofsByLastUpdate.equal_range(nodeid);
760 for (
auto &it = begin; it != end; it++) {
761 nodeRemoteProofs.emplace_back(*it);
764 return nodeRemoteProofs;
769 return view.count(proofid) > 0;
774 auto [begin, end] = view.equal_range(proofid);
775 return std::any_of(begin, end, [](
const auto &remoteProof) {
776 return remoteProof.present;
782 auto [begin, end] = remoteProofsView.equal_range(nodeid);
783 remoteProofsView.erase(begin, end);
787 auto it =
peers.find(peerid);
788 if (it ==
peers.end()) {
798 auto range = nview.equal_range(peerid);
799 for (
auto &nit = range.first; nit != range.second; ++nit) {
800 pendingNodes.emplace(it->getProofId(), nit->nodeid, nit->maxElements);
809 boost::make_tuple(peerid, Now<SteadyMilliseconds>())));
850 std::vector<Slot> newslots;
851 newslots.reserve(
peers.size());
853 uint64_t prevStop = 0;
855 for (
auto it =
peers.begin(); it !=
peers.end(); it++) {
856 if (it->node_count == 0) {
860 newslots.emplace_back(prevStop, it->getScore(), it->peerid);
861 prevStop = newslots.back().getStop();
862 if (!
peers.modify(it, [&](
Peer &p) { p.index = i++; })) {
867 slots = std::move(newslots);
869 const uint64_t saved =
slotCount - prevStop;
877 uint64_t prevStop = 0;
878 uint32_t scoreFromSlots = 0;
879 for (
size_t i = 0; i <
slots.size(); i++) {
896 if (it ==
peers.end() || it->index != i) {
901 scoreFromSlots +=
slots[i].getScore();
909 uint32_t scoreFromAllPeers = 0;
910 uint32_t scoreFromPeersWithNodes = 0;
912 std::unordered_set<COutPoint, SaltedOutpointHasher> peersUtxos;
913 for (
const auto &p :
peers) {
915 scoreFromAllPeers += p.getScore();
923 for (
const auto &ss : p.proof->getStakes()) {
924 const COutPoint &outpoint = ss.getStake().getUTXO();
931 if (proof != p.proof) {
936 if (!peersUtxos.emplace(outpoint).second) {
943 const auto count_nodes = [&]() {
946 auto begin = nview.lower_bound(
948 auto end = nview.upper_bound(
951 for (
auto it = begin; it != end; ++it) {
958 if (p.node_count != count_nodes()) {
963 if (p.node_count == 0) {
967 scoreFromPeersWithNodes += p.getScore();
969 if (p.index >=
slots.size() ||
slots[p.index].getPeerId() != p.peerid) {
974 if (
slots[p.index].getScore() != p.getScore()) {
984 if (p.node_count == 0 &&
1011 const uint64_t max) {
1014 size_t begin = 0, end = slots.size();
1015 uint64_t bottom = 0, top = max;
1018 while ((end - begin) > 8) {
1020 if (slot < bottom || slot >= top) {
1025 size_t i = begin + ((slot - bottom) * (end - begin) / (top - bottom));
1026 assert(begin <= i && i < end);
1029 if (slots[i].contains(slot)) {
1030 return slots[i].getPeerId();
1034 if (slots[i].precedes(slot)) {
1040 bottom = slots[begin].getStart();
1045 if (slots[i].follows(slot)) {
1047 top = slots[end].getStart();
1056 for (
size_t i = begin; i < end; i++) {
1058 if (slots[i].contains(slot)) {
1059 return slots[i].getPeerId();
1080 std::vector<std::pair<ProofId, CScript>> &winners) {
1091 auto registrationDelay = std::chrono::duration_cast<std::chrono::seconds>(
1093 auto maxRegistrationDelay =
1094 std::chrono::duration_cast<std::chrono::seconds>(
1096 auto minRegistrationDelay =
1097 std::chrono::duration_cast<std::chrono::seconds>(
1102 const int64_t targetRegistrationTime = refTime - registrationDelay.count();
1103 const int64_t maxRegistrationTime = refTime - minRegistrationDelay.count();
1104 const int64_t minRegistrationTime = refTime - maxRegistrationDelay.count();
1108 std::vector<ProofRef> selectedProofs;
1110 while (selectedProofs.size() <
peers.size()) {
1111 double bestRewardRank = std::numeric_limits<double>::max();
1113 int64_t selectedProofRegistrationTime{0};
1122 if (!peer.hasFinalized ||
1123 peer.registration_time.count() >= maxRegistrationTime) {
1127 if (std::find_if(selectedProofs.begin(), selectedProofs.end(),
1129 return peer.getProofId() == proof->getId();
1130 }) != selectedProofs.end()) {
1140 "Staking reward hash has a suspicious value of zero for "
1141 "proof %s and blockhash %s, skipping\n",
1142 peer.getProofId().ToString(), prevblockhash.
ToString());
1146 double proofRewardRank =
1152 proofRewardHash, proofRewardRank, peer.getProofId(),
1153 bestRewardHash, bestRewardRank,
1154 selectedProof ? selectedProof->getId()
1156 bestRewardRank = proofRewardRank;
1157 selectedProof = peer.proof;
1158 selectedProofRegistrationTime = peer.registration_time.count();
1159 bestRewardHash = proofRewardHash;
1163 if (!selectedProof) {
1168 if (!firstCompliantProof &&
1169 selectedProofRegistrationTime < targetRegistrationTime) {
1170 firstCompliantProof = selectedProof;
1173 selectedProofs.push_back(selectedProof);
1175 if (selectedProofRegistrationTime < minRegistrationTime &&
1176 !
isFlaky(selectedProof->getId())) {
1183 if (!firstCompliantProof) {
1187 winners.reserve(selectedProofs.size());
1190 for (
const ProofRef &proof : selectedProofs) {
1191 if (proof->getId() == firstCompliantProof->getId()) {
1192 winners.push_back({proof->getId(), proof->getPayoutScript()});
1196 for (
const ProofRef &proof : selectedProofs) {
1197 if (proof->getId() != firstCompliantProof->getId()) {
1198 winners.push_back({proof->getId(), proof->getPayoutScript()});
1228 auto &remoteProofsByNodeId =
remoteProofs.get<by_nodeid>();
1231 std::unordered_map<PeerId, std::unordered_set<ProofId, SaltedProofIdHasher>>
1235 double total_score{0};
1241 auto nodes_range = nview.equal_range(peerid);
1242 for (
auto &nit = nodes_range.first; nit != nodes_range.second; ++nit) {
1243 auto proofs_range = remoteProofsByNodeId.equal_range(nit->nodeid);
1244 for (
auto &proofit = proofs_range.first;
1245 proofit != proofs_range.second; ++proofit) {
1246 if (!proofit->present) {
1247 missing_per_peer[peerid].insert(proofit->proofid);
1253 double missing_score{0};
1256 for (
const auto &[peerid, missingProofs] : missing_per_peer) {
1257 if (missingProofs.size() > 3) {
1262 auto pit =
peers.find(peerid);
1263 if (pit ==
peers.end()) {
1268 if (missingProofs.count(proofid) > 0) {
1269 missing_score += pit->getScore();
1273 return (missing_score / total_score) > 0.3;
1278 auto &remoteProofsView =
remoteProofs.get<by_proofid>();
1279 auto [begin, end] = remoteProofsView.equal_range(proofid);
1283 return std::nullopt;
1286 double total_score{0};
1287 double present_score{0};
1288 double missing_score{0};
1290 for (
auto it = begin; it != end; it++) {
1291 auto nit =
nodes.find(it->nodeid);
1292 if (nit ==
nodes.end()) {
1297 const PeerId peerid = nit->peerid;
1299 auto pit =
peers.find(peerid);
1300 if (pit ==
peers.end()) {
1305 uint32_t node_count = pit->node_count;
1311 if (node_count == 0) {
1316 const double score = double(pit->getScore()) / node_count;
1318 total_score += score;
1320 present_score += score;
1322 missing_score += score;
1327 auto &peersByProofid =
peers.get<by_proofid>();
1330 bool present =
false;
1331 auto pit = peersByProofid.find(proofid);
1332 if (pit != peersByProofid.end()) {
1333 present = pit->node_count > 0;
1336 pit = peersByProofid.find(
localProof->getId());
1337 if (pit != peersByProofid.end()) {
1340 const double score =
1341 double(pit->getScore()) / (1 + pit->node_count);
1343 total_score += score;
1345 present_score += score;
1347 missing_score += score;
1352 if (present_score / total_score > 0.55) {
1353 return std::make_optional(
true);
1356 if (missing_score / total_score > 0.55) {
1357 return std::make_optional(
false);
1360 return std::nullopt;
1365 const fs::path dumpPathTmp = dumpPath +
".new";
1373 file << uint64_t(
peers.size());
1376 file << peer.hasFinalized;
1377 file << int64_t(peer.registration_time.count());
1378 file << int64_t(peer.nextPossibleConflictTime.count());
1382 throw std::runtime_error(
strprintf(
"Failed to commit to file %s",
1388 throw std::runtime_error(
strprintf(
"Rename failed from %s to %s",
1392 }
catch (
const std::exception &e) {
1406 std::unordered_set<ProofRef, SaltedProofHasher> ®isteredProofs) {
1407 registeredProofs.clear();
1411 if (file.IsNull()) {
1413 "Failed to open avalanche peers file from disk.\n");
1423 "Unsupported avalanche peers file version.\n");
1430 auto &peersByProofId =
peers.get<by_proofid>();
1432 for (uint64_t i = 0; i < numPeers; i++) {
1435 int64_t registrationTime;
1436 int64_t nextPossibleConflictTime;
1439 file >> hasFinalized;
1440 file >> registrationTime;
1441 file >> nextPossibleConflictTime;
1444 auto it = peersByProofId.find(proof->getId());
1445 if (it == peersByProofId.end()) {
1454 peersByProofId.modify(it, [&](
Peer &p) {
1457 std::chrono::seconds{registrationTime};
1459 std::chrono::seconds{nextPossibleConflictTime};
1462 registeredProofs.insert(proof);
1465 }
catch (
const std::exception &e) {
1467 "Failed to read the avalanche peers file data on disk: %s.\n",
1484 const ProofId &proofid = proof->getId();
1486 "Cached stake contender with proofid %s, payout %s at block "
1487 "%s (height %d) with id %s\n",
1500 prevblockhashout = contender->prevblockhash;
1501 if (contender->voteStatus != 0) {
1502 return contender->voteStatus;
1505 const ProofId &proofid = contender->proofid;
1520 auto &pview =
peers.get<by_proofid>();
1521 auto it = pview.find(proofid);
1522 if (it == pview.end() || !it->hasFinalized) {
1526 const int64_t refTime = std::min(contender->prevblocktime,
GetTime());
1527 const int64_t targetRegistrationTime =
1528 refTime - std::chrono::duration_cast<std::chrono::seconds>(
1531 if (it->registration_time.count() >= targetRegistrationTime) {
1546 std::vector<std::pair<ProofId, CScript>> &newWinners) {
1575 const std::vector<std::pair<ProofId, CScript>> winners,
size_t maxPollable,
1576 std::vector<StakeContenderId> &pollableContenders) {
1579 for (
const auto &winner : winners) {
1583 "Stake contender set as local winner: proofid %s, payout "
1584 "%s at block %s (height %d) with id %s\n",
1585 winner.first.ToString(),
HexStr(winner.second),
1595 pollableContenders) > 0) {
1600 "Stake contender set as best contender: id %s at block "
1611 const CBlockIndex *pindex,
const std::vector<CScript> &payoutScripts) {
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.
Non-refcounted RAII wrapper for FILE*.
The block chain is a tree shaped structure starting with the genesis block at the root,...
int64_t GetBlockTime() const
BlockHash GetBlockHash() const
int nHeight
height of the entry in the chain. The genesis block has height 0
void insert(Span< const uint8_t > vKey)
bool contains(Span< const uint8_t > vKey) const
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
bool Invalid(Result result, const std::string &reject_reason="", const std::string &debug_message="")
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 updateNextRequestTimeForResponse(NodeId nodeid, const Response &response)
bool isDangling(const ProofId &proofid) const
bool addNode(NodeId nodeid, const ProofId &proofid, size_t max_elements)
Node API.
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.
PendingNodeSet pendingNodes
bool verify() const
Perform consistency check on internal data structures.
bool hasRemoteProofStatus(const ProofId &proofid) const
bool forPeer(const ProofId &proofid, Callable &&func) const
void clearRemoteProofs(NodeId nodeid)
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.
void cleanupStakeContenders(const int requestedMinHeight)
Make some of the contender cache API available.
bool updateNextRequestTimeForPoll(NodeId nodeid, SteadyMilliseconds timeout, uint64_t round)
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)
void promoteStakeContendersToBlock(const CBlockIndex *pindex)
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)
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...
bool addOrUpdateNode(const PeerSet::iterator &it, NodeId nodeid, size_t max_elements)
uint64_t compact()
Trigger maintenance of internal data structures.
std::vector< Slot > slots
uint32_t totalPeersScore
Quorum management.
ProofPool danglingProofPool
StakeContenderCache stakeContenderCache
void setInvalid(const ProofId &proofid)
int getStakeContenderStatus(const StakeContenderId &contenderId, BlockHash &prevblockhashout) 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 rejectProof(const ProofId &proofid, RejectionMode mode=RejectionMode::DEFAULT)
ProofPool immatureProofPool
Amount stakeUtxoDustThreshold
RegistrationMode
Registration mode.
ProofPool conflictingProofPool
bool isStakingPreconsensusActivated() 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.
bool isInConflictingPool(const ProofId &proofid) const
bool isRemotelyPresentProof(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)
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)
ConflictingProofSet getConflicts(const ProofRef &proof) const
Return proofs in this pool that share any UTXO with proof.
bool getWinners(const BlockHash &prevblockhash, std::vector< std::pair< ProofId, CScript > > &winners) const
bool accept(const StakeContenderId &contenderId)
Helpers to set avalanche state of a contender.
void cleanup(const int requestedMinHeight)
size_t getPollableContenders(const BlockHash &prevblockhash, size_t maxPollable, std::vector< StakeContenderId > &pollableContenders) const
Get the best ranking contenders, accepted contenders ranking first.
bool reject(const StakeContenderId &contenderId)
bool setWinners(const CBlockIndex *pindex, const std::vector< CScript > &payoutScripts)
Set proof(s) that should be treated as winners (already finalized).
bool add(const CBlockIndex *pindex, const ProofRef &proof, uint8_t status=StakeContenderStatus::UNKNOWN)
Add a proof to consider in staking rewards pre-consensus.
std::optional< StakeContenderCacheInfo > getContenderInfo(const StakeContenderId &contenderId) const
void promoteToBlock(const CBlockIndex *activeTip, std::function< bool(const ProofId &proofid)> const &shouldPromote)
Promote cache entries to a the active chain tip.
int getVoteStatus(const StakeContenderId &contenderId, BlockHash &prevblockhashout) const
Get contender acceptance state for avalanche voting.
bool finalize(const StakeContenderId &contenderId)
std::string ToString() const
std::string GetHex() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
static const uint256 ZERO
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)
Rename src to dest.
bool FileCommit(FILE *file)
Ensure file contents are fully committed to disk, using a platform-specific feature analogous to fsyn...
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
#define LogPrint(category,...)
#define LogTrace(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
static std::string PathToString(const path &path)
Convert path object to byte string.
FILE * fopen(const fs::path &p, const char *mode)
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
static std::string ToString(const CService &ip)
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
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.
uint32_t getScore() const
uint64_t getStart() const
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
double ComputeProofRewardRank(uint32_t proofScore) const
To make sure the selection is properly weighted according to the proof score, we normalize the conten...
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#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