11#include <test/util/random.h>
12#include <test/util/setup_common.h>
14#include <validation.h>
16#include <boost/test/unit_test.hpp>
23struct PeerManagerFixture :
public TestChain100Setup {
24 PeerManagerFixture() {
27 ~PeerManagerFixture() {
33BOOST_FIXTURE_TEST_SUITE(stakecontendercache_tests, TestChain100Setup)
37 std::vector<CScript> manualWinners,
40 std::vector<std::pair<ProofId, CScript>> winners;
42 manualWinners.size() + acceptedWinners.size() + rejectedWinners.size();
46 !acceptedWinners.empty());
48 if (expectedSize == 0) {
49 BOOST_CHECK(!cache.getWinners(prevblockhash, winners));
53 BOOST_CHECK(cache.getWinners(prevblockhash, winners));
57 for (
size_t i = 0; i < manualWinners.size(); i++) {
62 for (
auto &proof : acceptedWinners) {
64 std::find_if(std::next(winners.begin(), manualWinners.size()),
65 std::next(winners.begin(), manualWinners.size() +
66 acceptedWinners.size()),
67 [&](std::pair<ProofId, CScript> &p) {
68 return p.first == proof->getId();
71 for (
auto &proof : rejectedWinners) {
73 std::find_if(std::next(winners.begin(), manualWinners.size() +
74 acceptedWinners.size()),
75 winners.end(), [&](std::pair<ProofId, CScript> &p) {
76 return p.first == proof->getId();
83 double previousRank = 0;
84 for (
auto it = std::next(winners.begin(), manualWinners.size());
85 it != std::next(winners.begin(),
86 manualWinners.size() + acceptedWinners.size());
91 previousRank = proofRank;
94 for (
auto it = std::next(winners.begin(),
95 manualWinners.size() + acceptedWinners.size());
96 it != winners.end(); it++) {
100 previousRank = proofRank;
106 const ProofRef &proof,
int expected) {
112 if (expected != -1) {
124 std::vector<int> initialStatuses = {
128 for (uint8_t initialStatus : initialStatuses) {
167 auto proofWinnerOnly =
169 auto proofAcceptedOnly =
171 auto proofAcceptedWinner =
206 std::vector<CScript> manualWinners = {
211 std::vector<ProofRef> proofs;
213 for (
int i = 0; i < 4; i++) {
221 for (
int i = 0; i < 5; i++) {
227 CheckWinners(cache, blockhash, {manualWinners[0]}, {}, {});
230 for (
int p = 0; p < 4; p++) {
257 for (
const auto &proof : proofs) {
268 CheckWinners(cache, blockhash, {manualWinners[0]}, {proofs[0]},
274 CheckWinners(cache, blockhash, manualWinners, {proofs[0]}, {proofs[2]});
278 std::vector<CScript> moreManualWinners = manualWinners;
279 for (
const auto &proof : proofs) {
280 moreManualWinners.push_back(proof->getPayoutScript());
283 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
286 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
291 for (
const auto &proof : proofs) {
295 {proofs[0], proofs[2]}, {});
299 for (
const auto &proof : proofs) {
303 {proofs[0], proofs[2]});
308 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
315 {proofs[0], proofs[1]}, {proofs[2]});
320 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
321 {proofs[1], proofs[2]});
323 pindex = pindex->
pprev;
328 for (
const auto &proof : proofs) {
329 manualWinners.push_back(proof->getPayoutScript());
334 for (
int i = 0; i < 5; i++) {
336 {proofs[1], proofs[2]});
337 for (
int p = 0; p < 4; p++) {
340 pindex = pindex->
pprev;
348 std::vector<ProofRef> proofs;
350 for (
int i = 0; i < 10; i++) {
356 std::vector<BlockHash> blockhashes{pindex->
GetBlockHash()};
357 pindex = pindex->
pprev;
358 for (
int i = 0; i < 3; i++) {
360 blockhashes.push_back(blockhash);
361 for (
const auto &proof : proofs) {
365 pindex = pindex->
pprev;
376 for (
int height : {0, 10, 50, 90, 97}) {
394 [](
const ProofId &proofid) { return false; });
409 CheckWinners(cache, blockhashes[3], {CScript()}, {}, {});
423 CheckWinners(cache, blockhashes[2], {CScript()}, {}, proofs);
427 [](
const ProofId &proofid) { return false; });
436 [](
const ProofId &proofid) { return false; });
454 for (
int height : {102, 200, 1000, 1000000}) {
456 for (
size_t i = 1; i < 3; i++) {
457 for (
const auto &proof : proofs) {
458 cache.
add(pindex, proof, m_rng.randbits(2));
463 std::vector<std::pair<ProofId, CScript>> winners;
466 pindex = pindex->
pprev;
483 for (
int height : {102, 200, 1000, 1000000}) {
485 CheckWinners(cache, blockhashes[0], {}, {}, {proofs[0]});
496 std::vector<ProofRef> proofs;
498 for (
size_t i = 0; i < 3; i++) {
505 std::vector<BlockHash> blockhashes;
506 for (
size_t i = 0; i < 3; i++) {
508 pindex = pindex->
pprev;
512 for (
size_t i = 0; i < 3; i++) {
514 blockhashes.push_back(blockhash);
517 pindex = pindex->
pprev;
522 for (
int height = 95; height <= 100; height++) {
527 CheckWinners(cache, blockhashes[3], {}, {}, {proofs[0]});
528 CheckWinners(cache, blockhashes[4], {}, {}, {proofs[1]});
529 CheckWinners(cache, blockhashes[5], {}, {}, {proofs[2]});
534 [](
const ProofId &proofid) { return true; });
538 for (
auto &proof : proofs) {
547 CheckWinners(cache, blockhashes[3], {}, {}, {proofs[0]});
548 CheckWinners(cache, blockhashes[4], {}, {}, {proofs[1]});
549 CheckWinners(cache, blockhashes[5], {}, {}, {proofs[2]});
556 for (
auto &proof : proofs) {
568 for (
auto &proof : proofs) {
583 [](
const ProofId &proofid) { return true; });
584 for (
auto &proof : proofs) {
597 return proofid != proofs[2]->getId();
599 for (
auto &proof : proofs) {
615 const size_t maxPollable = 12;
616 std::vector<StakeContenderId> contenders;
620 size_t numAccepted = 0;
621 for (
size_t c = 0; c < maxPollable * 2; c++) {
628 numAccepted += cache.
getVoteStatus(contenderId, dummy) == 0 ? 1 : 0;
633 contenders) <= maxPollable);
637 size_t countAccepted = 0;
638 for (
const auto &contender : contenders) {
645 countAccepted += cache.
getVoteStatus(contender, dummy) == 0 ? 1 : 0;
653BOOST_AUTO_TEST_SUITE_END()
#define Assert(val)
Identity function.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
void ClearForcedArg(const std::string &strArg)
Remove a forced arg setting, used only in testing.
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
BlockHash GetBlockHash() const
int nHeight
height of the entry in the chain. The genesis block has height 0
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Chainstate stores and provides an API to update our local knowledge of the current best chain.
CChain m_chain
The current chain of blockheaders we consult and build on.
const ProofId & getId() const
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 hasAcceptedWinner(const BlockHash &prevblockhash) const
True if any accepted contender is in the winner set for prevblockhash.
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.
bool isEmpty() const
For tests.
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)
ProofRef buildRandomProof(Chainstate &active_chainstate, uint32_t score, int height, const CKey &masterKey)
constexpr uint32_t MIN_VALID_PROOF_SCORE
Implement std::hash so RCUPtr can be used as a key for maps or sets.
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
static void CheckVoteStatus(StakeContenderCache &cache, const BlockHash &prevblockhash, const ProofRef &proof, int expected)
BOOST_FIXTURE_TEST_CASE(promote_tests, PeerManagerFixture)
BOOST_AUTO_TEST_CASE(vote_status_tests)
static void CheckWinners(StakeContenderCache &cache, const BlockHash &prevblockhash, std::vector< CScript > manualWinners, std::vector< ProofRef > acceptedWinners, std::vector< ProofRef > rejectedWinners)
A BlockHash is a unqiue identifier for a block.
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...