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);
56 std::function<
bool(
const ProofId &proofid)>
const &shouldPromote) {
63 const int height = activeTip->
nHeight;
69 std::vector<StakeContenderCacheEntry> promotedEntries;
72 const ProofId &proofid = contender.proofid;
73 bool promoted =
false;
74 if (shouldPromote(proofid)) {
76 blockhash, height, blocktime, proofid,
82 "Contender with proofid %s, payout %s was%s promoted to "
83 "block %s (height %d) (old id %s, next id %s)\n",
85 promoted ?
"" :
" NOT", blockhash.
ToString(), height,
86 contender.getStakeContenderId().ToString(),
89 contenders.insert(promotedEntries.begin(), promotedEntries.end());
145 auto &view =
contenders.get<by_stakecontenderid>();
146 auto it = view.find(contenderId);
147 if (it == view.end()) {
158 if (it->isAccepted()) {
159 contenderInfo.voteStatus = 0;
160 return contenderInfo;
163 auto &manualWinnersView =
manualWinners.get<by_prevblockhash>();
164 auto manualWinnerIt = manualWinnersView.find(it->prevblockhash);
166 for (
auto &payoutScript : manualWinnerIt->payoutScripts) {
167 if (payoutScript == it->payoutScriptPubkey) {
168 contenderInfo.voteStatus = 0;
169 return contenderInfo;
174 return contenderInfo;
189 const BlockHash &prevblockhash,
size_t maxPollable,
190 std::vector<StakeContenderId> &pollableContenders)
const {
191 std::vector<const StakeContenderCacheEntry *> rankedContenders;
192 auto &view =
contenders.get<by_prevblockhash>();
193 auto [begin, end] = view.equal_range(prevblockhash);
194 for (
auto it = begin; it != end; it++) {
195 rankedContenders.push_back(&(*it));
199 std::sort(rankedContenders.begin(), rankedContenders.end(),
202 if (left->isAccepted() != right->isAccepted()) {
204 return left->isAccepted();
214 left->
proofid, rightContenderId,
220 size_t numPollable = std::min(rankedContenders.size(), maxPollable);
221 std::sort(rankedContenders.begin(), rankedContenders.begin() + numPollable,
224 double leftRank = left->computeRewardRank();
225 double rightRank = right->computeRewardRank();
226 const StakeContenderId &leftContenderId =
227 left->getStakeContenderId();
228 const StakeContenderId &rightContenderId =
229 right->getStakeContenderId();
230 return RewardRankComparator()(leftContenderId, leftRank,
231 left->proofid, rightContenderId,
232 rightRank, right->proofid);
236 pollableContenders.clear();
237 pollableContenders.reserve(numPollable);
238 for (
size_t i = 0; i < numPollable; i++) {
239 pollableContenders.push_back(
240 rankedContenders[i]->getStakeContenderId());
243 return pollableContenders.size();
246bool StakeContenderCache::getWinners(
248 std::vector<std::pair<ProofId, CScript>> &winners)
const {
250 std::vector<const StakeContenderCacheEntry *> rankedWinners;
251 auto &view = contenders.get<by_prevblockhash>();
252 auto [begin, end] = view.equal_range(prevblockhash);
253 for (
auto it = begin; it != end; it++) {
254 if (it->isInWinnerSet()) {
255 rankedWinners.push_back(&(*it));
259 std::sort(rankedWinners.begin(), rankedWinners.end(),
262 if (left->isAccepted() != right->isAccepted()) {
264 return left->isAccepted();
274 left->
proofid, rightContenderId,
281 auto &manualWinnersView = manualWinners.get<by_prevblockhash>();
282 auto manualWinnerIt = manualWinnersView.find(prevblockhash);
283 if (manualWinnerIt != manualWinners.end()) {
284 winners.reserve(manualWinnerIt->payoutScripts.size() +
285 rankedWinners.size());
287 for (
auto &payoutScript : manualWinnerIt->payoutScripts) {
288 winners.push_back({
ProofId(), payoutScript});
291 winners.reserve(rankedWinners.size());
295 for (
const auto &rankedWinner : rankedWinners) {
297 {rankedWinner->proofid, rankedWinner->payoutScriptPubkey});
300 return winners.size() > 0;
303bool StakeContenderCache::hasAcceptedWinner(
305 auto &view = contenders.get<by_prevblockhash>();
306 auto [begin, end] = view.equal_range(prevblockhash);
307 for (
auto it = begin; it != end; it++) {
308 if (it->isInWinnerSet() && it->isAccepted()) {
size_t getPollableContenders(const BlockHash &prevblockhash, size_t maxPollable, std::vector< StakeContenderId > &pollableContenders) const
Get the best ranking contenders, accepted contenders ranking first.
double computeRewardRank() const
StakeContenderId getStakeContenderId() const