21 std::set<BlockHash> hashesToErase;
23 for (
auto it = mwHeightView.begin();
24 it != mwHeightView.lower_bound(minHeight); it++) {
25 hashesToErase.insert(it->prevblockhash);
28 auto &cHeightView =
contenders.get<by_blockheight>();
29 for (
auto it = cHeightView.begin();
30 it != cHeightView.lower_bound(minHeight); it++) {
31 hashesToErase.insert(it->prevblockhash);
34 for (
const auto &blockhash : hashesToErase) {
36 auto [mwHashBegin, mwHashEnd] = mwHashView.equal_range(blockhash);
37 mwHashView.erase(mwHashBegin, mwHashEnd);
39 auto &cHashView =
contenders.get<by_prevblockhash>();
40 auto [cHashBegin, cHashEnd] = cHashView.equal_range(blockhash);
41 cHashView.erase(cHashBegin, cHashEnd);
49 status, proof->getPayoutScript(), proof->getScore())
55 std::function<
bool(
const ProofId &proofid)>
const &shouldPromote) {
62 const int height = activeTip->
nHeight;
67 std::vector<StakeContenderCacheEntry> promotedEntries;
70 const ProofId &proofid = contender.proofid;
71 bool promoted =
false;
72 if (shouldPromote(proofid)) {
75 contender.payoutScriptPubkey, contender.score));
79 "Contender with proofid %s, payout %s was%s promoted to "
80 "block %s (height %d) (old id %s, next id %s)\n",
82 promoted ?
"" :
" NOT", blockhash.
ToString(), height,
83 contender.getStakeContenderId().ToString(),
86 contenders.insert(promotedEntries.begin(), promotedEntries.end());
90 const CBlockIndex *pindex,
const std::vector<CScript> &payoutScripts) {
93 auto it = view.find(prevblockhash);
94 if (it == view.end()) {
96 .emplace(prevblockhash, pindex->
nHeight, payoutScripts)
104 auto &view =
contenders.get<by_stakecontenderid>();
105 auto it = view.find(contenderId);
106 if (it == view.end()) {
116 auto &view =
contenders.get<by_stakecontenderid>();
117 auto it = view.find(contenderId);
118 if (it == view.end()) {
129 auto &view =
contenders.get<by_stakecontenderid>();
130 auto it = view.find(contenderId);
131 if (it == view.end()) {
142 auto &view =
contenders.get<by_stakecontenderid>();
143 auto it = view.find(contenderId);
144 if (it == view.end()) {
148 prevblockhashout = it->prevblockhash;
151 if (it->isAccepted()) {
156 auto &manualWinnersView =
manualWinners.get<by_prevblockhash>();
157 auto manualWinnerIt = manualWinnersView.find(it->prevblockhash);
159 for (
auto &payoutScript : manualWinnerIt->payoutScripts) {
160 if (payoutScript == it->payoutScriptPubkey) {
171 const BlockHash &prevblockhash,
size_t maxPollable,
172 std::vector<StakeContenderId> &pollableContenders)
const {
173 std::vector<const StakeContenderCacheEntry *> rankedContenders;
174 auto &view =
contenders.get<by_prevblockhash>();
175 auto [begin, end] = view.equal_range(prevblockhash);
176 for (
auto it = begin; it != end; it++) {
177 rankedContenders.push_back(&(*it));
181 std::sort(rankedContenders.begin(), rankedContenders.end(),
184 if (left->isAccepted() != right->isAccepted()) {
186 return left->isAccepted();
196 left->
proofid, rightContenderId,
202 size_t numPollable = std::min(rankedContenders.size(), maxPollable);
203 std::sort(rankedContenders.begin(), rankedContenders.begin() + numPollable,
206 double leftRank = left->computeRewardRank();
207 double rightRank = right->computeRewardRank();
208 const StakeContenderId &leftContenderId =
209 left->getStakeContenderId();
210 const StakeContenderId &rightContenderId =
211 right->getStakeContenderId();
212 return RewardRankComparator()(leftContenderId, leftRank,
213 left->proofid, rightContenderId,
214 rightRank, right->proofid);
218 pollableContenders.clear();
219 pollableContenders.reserve(numPollable);
220 for (
size_t i = 0; i < numPollable; i++) {
221 pollableContenders.push_back(
222 rankedContenders[i]->getStakeContenderId());
225 return pollableContenders.size();
228bool StakeContenderCache::getWinners(
230 std::vector<std::pair<ProofId, CScript>> &winners)
const {
232 std::vector<const StakeContenderCacheEntry *> rankedWinners;
233 auto &view = contenders.get<by_prevblockhash>();
234 auto [begin, end] = view.equal_range(prevblockhash);
235 for (
auto it = begin; it != end; it++) {
236 if (it->isInWinnerSet()) {
237 rankedWinners.push_back(&(*it));
241 std::sort(rankedWinners.begin(), rankedWinners.end(),
244 if (left->isAccepted() != right->isAccepted()) {
246 return left->isAccepted();
256 left->
proofid, rightContenderId,
263 auto &manualWinnersView = manualWinners.get<by_prevblockhash>();
264 auto manualWinnerIt = manualWinnersView.find(prevblockhash);
265 if (manualWinnerIt != manualWinners.end()) {
266 winners.reserve(manualWinnerIt->payoutScripts.size() +
267 rankedWinners.size());
269 for (
auto &payoutScript : manualWinnerIt->payoutScripts) {
270 winners.push_back({
ProofId(), payoutScript});
273 winners.reserve(rankedWinners.size());
277 for (
const auto &rankedWinner : rankedWinners) {
279 {rankedWinner->proofid, rankedWinner->payoutScriptPubkey});
282 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
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.
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
#define LogPrintLevel(category, level,...)
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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 ...
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.