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;
160 for (
int i = 0; i < 4; i++) {
168 for (
int i = 0; i < 5; i++) {
174 CheckWinners(cache, blockhash, {manualWinners[0]}, {}, {});
177 for (
int p = 0; p < 4; p++) {
204 for (
const auto &proof : proofs) {
215 CheckWinners(cache, blockhash, {manualWinners[0]}, {proofs[0]},
221 CheckWinners(cache, blockhash, manualWinners, {proofs[0]}, {proofs[2]});
225 std::vector<CScript> moreManualWinners = manualWinners;
226 for (
const auto &proof : proofs) {
227 moreManualWinners.push_back(proof->getPayoutScript());
230 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
233 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
238 for (
const auto &proof : proofs) {
242 {proofs[0], proofs[2]}, {});
246 for (
const auto &proof : proofs) {
250 {proofs[0], proofs[2]});
255 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
262 {proofs[0], proofs[1]}, {proofs[2]});
267 CheckWinners(cache, blockhash, moreManualWinners, {proofs[0]},
268 {proofs[1], proofs[2]});
270 pindex = pindex->
pprev;
275 for (
const auto &proof : proofs) {
276 manualWinners.push_back(proof->getPayoutScript());
281 for (
int i = 0; i < 5; i++) {
283 {proofs[1], proofs[2]});
284 for (
int p = 0; p < 4; p++) {
287 pindex = pindex->
pprev;
295 std::vector<ProofRef> proofs;
297 for (
int i = 0; i < 10; i++) {
303 std::vector<BlockHash> blockhashes{pindex->
GetBlockHash()};
304 pindex = pindex->
pprev;
305 for (
int i = 0; i < 3; i++) {
307 blockhashes.push_back(blockhash);
308 for (
const auto &proof : proofs) {
312 pindex = pindex->
pprev;
323 for (
int height : {0, 10, 50, 90, 97}) {
341 [](
const ProofId &proofid) { return false; });
356 CheckWinners(cache, blockhashes[3], {CScript()}, {}, {});
370 CheckWinners(cache, blockhashes[2], {CScript()}, {}, proofs);
374 [](
const ProofId &proofid) { return false; });
383 [](
const ProofId &proofid) { return false; });
401 for (
int height : {102, 200, 1000, 1000000}) {
403 for (
size_t i = 1; i < 3; i++) {
404 for (
const auto &proof : proofs) {
405 cache.
add(pindex, proof, InsecureRandBits(2));
410 std::vector<std::pair<ProofId, CScript>> winners;
413 pindex = pindex->
pprev;
430 for (
int height : {102, 200, 1000, 1000000}) {
432 CheckWinners(cache, blockhashes[0], {}, {}, {proofs[0]});
443 std::vector<ProofRef> proofs;
445 for (
size_t i = 0; i < 3; i++) {
452 std::vector<BlockHash> blockhashes;
453 for (
size_t i = 0; i < 3; i++) {
455 pindex = pindex->
pprev;
459 for (
size_t i = 0; i < 3; i++) {
461 blockhashes.push_back(blockhash);
464 pindex = pindex->
pprev;
469 for (
int height = 95; height <= 100; height++) {
474 CheckWinners(cache, blockhashes[3], {}, {}, {proofs[0]});
475 CheckWinners(cache, blockhashes[4], {}, {}, {proofs[1]});
476 CheckWinners(cache, blockhashes[5], {}, {}, {proofs[2]});
481 [](
const ProofId &proofid) { return true; });
485 for (
auto &proof : proofs) {
494 CheckWinners(cache, blockhashes[3], {}, {}, {proofs[0]});
495 CheckWinners(cache, blockhashes[4], {}, {}, {proofs[1]});
496 CheckWinners(cache, blockhashes[5], {}, {}, {proofs[2]});
503 for (
auto &proof : proofs) {
515 for (
auto &proof : proofs) {
530 [](
const ProofId &proofid) { return true; });
531 for (
auto &proof : proofs) {
544 return proofid != proofs[2]->getId();
546 for (
auto &proof : proofs) {
562 const size_t maxPollable = 12;
563 std::vector<StakeContenderId> contenders;
567 size_t numAccepted = 0;
568 for (
size_t c = 0; c < maxPollable * 2; c++) {
575 numAccepted += cache.
getVoteStatus(contenderId, dummy) == 0 ? 1 : 0;
580 contenders) <= maxPollable);
584 size_t countAccepted = 0;
585 for (
const auto &contender : contenders) {
592 countAccepted += cache.
getVoteStatus(contender, dummy) == 0 ? 1 : 0;
600BOOST_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...