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();
43 if (expectedSize == 0) {
44 BOOST_CHECK(!cache.getWinners(prevblockhash, winners));
48 BOOST_CHECK(cache.getWinners(prevblockhash, winners));
52 for (
size_t i = 0; i < manualWinners.size(); i++) {
57 for (
auto &proof : acceptedWinners) {
59 std::find_if(std::next(winners.begin(), manualWinners.size()),
60 std::next(winners.begin(), manualWinners.size() +
61 acceptedWinners.size()),
62 [&](std::pair<ProofId, CScript> &p) {
63 return p.first == proof->getId();
66 for (
auto &proof : rejectedWinners) {
68 std::find_if(std::next(winners.begin(), manualWinners.size() +
69 acceptedWinners.size()),
70 winners.end(), [&](std::pair<ProofId, CScript> &p) {
71 return p.first == proof->getId();
78 double previousRank = 0;
79 for (
auto it = std::next(winners.begin(), manualWinners.size());
80 it != std::next(winners.begin(),
81 manualWinners.size() + acceptedWinners.size());
86 previousRank = proofRank;
89 for (
auto it = std::next(winners.begin(),
90 manualWinners.size() + acceptedWinners.size());
91 it != winners.end(); it++) {
95 previousRank = proofRank;
101 const ProofRef &proof,
int expected) {
107 if (expected != -1) {
119 std::vector<int> initialStatuses = {
123 for (uint8_t initialStatus : initialStatuses) {
153 std::vector<CScript> manualWinners = {
158 std::vector<ProofRef> proofs;
159 for (
int i = 0; i < 4; i++) {
167 for (
int i = 0; i < 5; i++) {
173 CheckWinners(cache, blockhash, {manualWinners[0]}, {}, {});
176 for (
int p = 0; p < 4; p++) {
203 for (
const auto &proof : proofs) {
214 CheckWinners(cache, blockhash, {manualWinners[0]}, {proofs[0]},
220 CheckWinners(cache, blockhash, manualWinners, {proofs[0]}, {proofs[2]});
224 std::vector<CScript> moreManualWinners = manualWinners;
225 for (
const auto &proof : proofs) {
226 moreManualWinners.push_back(proof->getPayoutScript());
229 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
232 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
237 for (
const auto &proof : proofs) {
241 {proofs[0], proofs[2]}, {});
245 for (
const auto &proof : proofs) {
249 {proofs[0], proofs[2]});
254 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
261 {proofs[0], proofs[1]}, {proofs[2]});
266 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
267 {proofs[1], proofs[2]});
269 pindex = pindex->
pprev;
274 for (
const auto &proof : proofs) {
275 manualWinners.push_back(proof->getPayoutScript());
280 for (
int i = 0; i < 5; i++) {
282 {proofs[1], proofs[2]});
283 for (
int p = 0; p < 4; p++) {
286 pindex = pindex->
pprev;
294 std::vector<ProofRef> proofs;
295 for (
int i = 0; i < 10; i++) {
301 std::vector<BlockHash> blockhashes{pindex->
GetBlockHash()};
302 pindex = pindex->
pprev;
303 for (
int i = 0; i < 3; i++) {
305 blockhashes.push_back(blockhash);
306 for (
const auto &proof : proofs) {
310 pindex = pindex->
pprev;
321 for (
int height : {0, 10, 50, 90, 97}) {
339 [](
const ProofId &proofid) { return false; });
354 CheckWinners(cache, blockhashes[3], {CScript()}, {}, {});
368 CheckWinners(cache, blockhashes[2], {CScript()}, {}, proofs);
372 [](
const ProofId &proofid) { return false; });
381 [](
const ProofId &proofid) { return false; });
399 for (
int height : {102, 200, 1000, 1000000}) {
401 for (
size_t i = 1; i < 3; i++) {
402 for (
const auto &proof : proofs) {
403 cache.
add(pindex, proof, InsecureRandBits(2));
408 std::vector<std::pair<ProofId, CScript>> winners;
411 pindex = pindex->
pprev;
428 for (
int height : {102, 200, 1000, 1000000}) {
430 CheckWinners(cache, blockhashes[0], {}, {}, {proofs[0]});
441 std::vector<ProofRef> proofs;
442 for (
size_t i = 0; i < 3; i++) {
449 std::vector<BlockHash> blockhashes;
450 for (
size_t i = 0; i < 3; i++) {
452 pindex = pindex->
pprev;
456 for (
size_t i = 0; i < 3; i++) {
458 blockhashes.push_back(blockhash);
461 pindex = pindex->
pprev;
466 for (
int height = 95; height <= 100; height++) {
471 CheckWinners(cache, blockhashes[3], {}, {}, {proofs[0]});
472 CheckWinners(cache, blockhashes[4], {}, {}, {proofs[1]});
473 CheckWinners(cache, blockhashes[5], {}, {}, {proofs[2]});
478 [](
const ProofId &proofid) { return true; });
482 for (
auto &proof : proofs) {
491 CheckWinners(cache, blockhashes[3], {}, {}, {proofs[0]});
492 CheckWinners(cache, blockhashes[4], {}, {}, {proofs[1]});
493 CheckWinners(cache, blockhashes[5], {}, {}, {proofs[2]});
500 for (
auto &proof : proofs) {
512 for (
auto &proof : proofs) {
527 [](
const ProofId &proofid) { return true; });
528 for (
auto &proof : proofs) {
541 return proofid != proofs[2]->getId();
543 for (
auto &proof : proofs) {
559 const size_t maxPollable = 12;
560 std::vector<StakeContenderId> contenders;
564 size_t numAccepted = 0;
565 for (
size_t c = 0; c < maxPollable * 2; c++) {
572 numAccepted += cache.
getVoteStatus(contenderId, dummy) == 0 ? 1 : 0;
577 contenders) <= maxPollable);
581 size_t countAccepted = 0;
582 for (
const auto &contender : contenders) {
589 countAccepted += cache.
getVoteStatus(contender, dummy) == 0 ? 1 : 0;
597BOOST_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
Cache to track stake contenders for recent blocks.
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.
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...