19 std::set<BlockHash> hashesToErase;
21 for (
auto it = mwHeightView.begin();
22 it != mwHeightView.lower_bound(minHeight); it++) {
23 hashesToErase.insert(it->prevblockhash);
26 auto &cHeightView =
contenders.get<by_blockheight>();
27 for (
auto it = cHeightView.begin();
28 it != cHeightView.lower_bound(minHeight); it++) {
29 hashesToErase.insert(it->prevblockhash);
32 for (
const auto &blockhash : hashesToErase) {
34 auto [mwHashBegin, mwHashEnd] = mwHashView.equal_range(blockhash);
35 mwHashView.erase(mwHashBegin, mwHashEnd);
37 auto &cHashView =
contenders.get<by_prevblockhash>();
38 auto [cHashBegin, cHashEnd] = cHashView.equal_range(blockhash);
39 cHashView.erase(cHashBegin, cHashEnd);
47 status, proof->getPayoutScript(), proof->getScore())
59 const int height = activeTip->
nHeight;
62 const ProofId &proofid = contender.proofid;
67 contender.payoutScriptPubkey, contender.score);
73 const CBlockIndex *pindex,
const std::vector<CScript> &payoutScripts) {
76 auto it = view.find(prevblockhash);
77 if (it == view.end()) {
79 .emplace(prevblockhash, pindex->
nHeight, payoutScripts)
87 auto &view =
contenders.get<by_stakecontenderid>();
88 auto it = view.find(contenderId);
89 if (it == view.end()) {
99 auto &view =
contenders.get<by_stakecontenderid>();
100 auto it = view.find(contenderId);
101 if (it == view.end()) {
112 auto &view =
contenders.get<by_stakecontenderid>();
113 auto it = view.find(contenderId);
114 if (it == view.end()) {
125 auto &view =
contenders.get<by_stakecontenderid>();
126 auto it = view.find(contenderId);
127 if (it == view.end()) {
131 prevblockhashout = it->prevblockhash;
134 if (it->isAccepted()) {
139 auto &manualWinnersView =
manualWinners.get<by_prevblockhash>();
140 auto manualWinnerIt = manualWinnersView.find(it->prevblockhash);
142 for (
auto &payoutScript : manualWinnerIt->payoutScripts) {
143 if (payoutScript == it->payoutScriptPubkey) {
154 const BlockHash &prevblockhash,
size_t maxPollable,
155 std::vector<StakeContenderId> &pollableContenders)
const {
156 std::vector<const StakeContenderCacheEntry *> rankedContenders;
157 auto &view =
contenders.get<by_prevblockhash>();
158 auto [begin, end] = view.equal_range(prevblockhash);
159 for (
auto it = begin; it != end; it++) {
160 rankedContenders.push_back(&(*it));
164 std::sort(rankedContenders.begin(), rankedContenders.end(),
167 if (left->isAccepted() != right->isAccepted()) {
169 return left->isAccepted();
179 left->
proofid, rightContenderId,
185 size_t numPollable = std::min(rankedContenders.size(), maxPollable);
186 std::sort(rankedContenders.begin(), rankedContenders.begin() + numPollable,
189 double leftRank = left->computeRewardRank();
190 double rightRank = right->computeRewardRank();
191 const StakeContenderId &leftContenderId =
192 left->getStakeContenderId();
193 const StakeContenderId &rightContenderId =
194 right->getStakeContenderId();
195 return RewardRankComparator()(leftContenderId, leftRank,
196 left->proofid, rightContenderId,
197 rightRank, right->proofid);
201 pollableContenders.clear();
202 pollableContenders.reserve(numPollable);
203 for (
size_t i = 0; i < numPollable; i++) {
204 pollableContenders.push_back(
205 rankedContenders[i]->getStakeContenderId());
208 return pollableContenders.size();
211bool StakeContenderCache::getWinners(
213 std::vector<std::pair<ProofId, CScript>> &winners)
const {
215 std::vector<const StakeContenderCacheEntry *> rankedWinners;
216 auto &view = contenders.get<by_prevblockhash>();
217 auto [begin, end] = view.equal_range(prevblockhash);
218 for (
auto it = begin; it != end; it++) {
219 if (it->isInWinnerSet()) {
220 rankedWinners.push_back(&(*it));
224 std::sort(rankedWinners.begin(), rankedWinners.end(),
227 if (left->isAccepted() != right->isAccepted()) {
229 return left->isAccepted();
239 left->
proofid, rightContenderId,
246 auto &manualWinnersView = manualWinners.get<by_prevblockhash>();
247 auto manualWinnerIt = manualWinnersView.find(prevblockhash);
248 if (manualWinnerIt != manualWinners.end()) {
249 winners.reserve(manualWinnerIt->payoutScripts.size() +
250 rankedWinners.size());
252 for (
auto &payoutScript : manualWinnerIt->payoutScripts) {
253 winners.push_back({
ProofId(), payoutScript});
256 winners.reserve(rankedWinners.size());
260 for (
const auto &rankedWinner : rankedWinners) {
262 {rankedWinner->proofid, rankedWinner->payoutScriptPubkey});
265 return winners.size() > 0;
The block chain is a tree shaped structure starting with the genesis block at the root,...
BlockHash GetBlockHash() const
int nHeight
height of the entry in the chain. The genesis block has height 0
bool isDangling(const ProofId &proofid) const
bool isRemoteProof(const ProofId &proofid) const
bool isBoundToPeer(const ProofId &proofid) const
ManualWinnersSet manualWinners
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.
int getVoteStatus(const StakeContenderId &contenderId, BlockHash &prevblockhashout) const
Get contender acceptance state for avalanche voting.
bool finalize(const StakeContenderId &contenderId)
void promoteToBlock(const CBlockIndex *activeTip, PeerManager &pm)
Promote cache entries to a the active chain tip.
A BlockHash is a unqiue identifier for a block.
double computeRewardRank() const
StakeContenderId getStakeContenderId() const
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...