Bitcoin ABC 0.30.7
P2P Digital Currency
stakecontendercache_tests.cpp
Go to the documentation of this file.
1// Copyright (c) 2024 The Bitcoin developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
6
8#include <script/script.h>
9
10#include <avalanche/test/util.h>
11#include <test/util/random.h>
12#include <test/util/setup_common.h>
13#include <util/time.h>
14
15#include <boost/test/unit_test.hpp>
16
17#include <limits>
18
19using namespace avalanche;
20
21namespace {
22struct PeerManagerFixture : public TestChain100Setup {
23 PeerManagerFixture() {
24 gArgs.ForceSetArg("-avaproofstakeutxoconfirmations", "1");
25 }
26 ~PeerManagerFixture() {
27 gArgs.ClearForcedArg("-avaproofstakeutxoconfirmations");
28 }
29};
30} // namespace
31
32BOOST_FIXTURE_TEST_SUITE(stakecontendercache_tests, TestChain100Setup)
33
35 const BlockHash &prevblockhash,
36 std::vector<CScript> manualWinners,
37 std::vector<ProofRef> avalancheWinners) {
38 std::vector<CScript> winners;
39 size_t expectedSize = manualWinners.size() + avalancheWinners.size();
40 if (expectedSize == 0) {
41 BOOST_CHECK(!cache.getWinners(prevblockhash, winners));
42 return;
43 }
44
45 BOOST_CHECK(cache.getWinners(prevblockhash, winners));
46 BOOST_CHECK_EQUAL(winners.size(), expectedSize);
47
48 // Manual winners are always first and in order
49 for (size_t i = 0; i < manualWinners.size(); i++) {
50 BOOST_CHECK(winners[i] == manualWinners[i]);
51 }
52
53 // Rest of the the winners are only those determined by avalanche.
54 // For each winning payout script, find all avalancheWinners with the same
55 // payout script.
56 std::vector<std::vector<ProofRef>> possibleWinningProofs;
57 for (auto it = std::next(winners.begin(), manualWinners.size());
58 it != winners.end(); it++) {
59 possibleWinningProofs.push_back(std::vector<ProofRef>());
60 for (const auto &proof : avalancheWinners) {
61 if (proof->getPayoutScript() == *it) {
62 possibleWinningProofs.back().push_back(proof);
63 }
64 }
65 BOOST_CHECK(possibleWinningProofs.back().size() > 0);
66 }
67 BOOST_CHECK_EQUAL(possibleWinningProofs.size(), avalancheWinners.size());
68
69 // Verify the winner order such that the best (lowest) reward ranked proof's
70 // payout script is always before payout scripts from proofs with worse
71 // (higher) reward ranks.
72 double previousRank = 0;
73 for (auto possibleWinningProofList : possibleWinningProofs) {
74 double lowestRank = std::numeric_limits<double>::max();
75 for (const auto &proof : possibleWinningProofList) {
76 double proofRank = StakeContenderId(prevblockhash, proof->getId())
77 .ComputeProofRewardRank(proof->getScore());
78 if (proofRank < lowestRank) {
79 lowestRank = proofRank;
80 }
81 }
82
83 BOOST_CHECK(previousRank < lowestRank);
84 previousRank = lowestRank;
85 }
86}
87
89 const BlockHash &prevblockhash,
90 const ProofRef &proof, int expected) {
91 BlockHash checkprevblockhash;
93 cache.getVoteStatus(StakeContenderId(prevblockhash, proof->getId()),
94 checkprevblockhash),
95 expected);
96 if (expected != -1) {
97 BOOST_CHECK_EQUAL(prevblockhash, checkprevblockhash);
98 }
99}
100
101BOOST_AUTO_TEST_CASE(vote_status_tests) {
102 Chainstate &active_chainstate = Assert(m_node.chainman)->ActiveChainstate();
104
105 CBlockIndex *pindex = active_chainstate.m_chain.Tip();
106 const BlockHash &blockhash = pindex->GetBlockHash();
107
108 std::vector<int> initialStatuses = {
112 for (uint8_t initialStatus : initialStatuses) {
113 auto proof = buildRandomProof(active_chainstate, MIN_VALID_PROOF_SCORE);
114
115 // Unknown contender
116 CheckVoteStatus(cache, blockhash, proof, -1);
117
118 // Add the contender and check its vote after avalanche updates
119 BOOST_CHECK(cache.add(pindex, proof, initialStatus));
120 CheckVoteStatus(cache, blockhash, proof,
121 !(initialStatus & StakeContenderStatus::ACCEPTED));
122
123 cache.accept(StakeContenderId(blockhash, proof->getId()));
124 CheckVoteStatus(cache, blockhash, proof, 0);
125
126 cache.reject(StakeContenderId(blockhash, proof->getId()));
127 CheckVoteStatus(cache, blockhash, proof, 1);
128
129 cache.finalize(StakeContenderId(blockhash, proof->getId()));
130 CheckVoteStatus(cache, blockhash, proof, 0);
131
132 cache.invalidate(StakeContenderId(blockhash, proof->getId()));
133 CheckVoteStatus(cache, blockhash, proof, 1);
134
135 // Add the proof as a manual winner. It should always be accepted.
136 BOOST_CHECK(cache.setWinners(pindex, {proof->getPayoutScript()}));
137 CheckVoteStatus(cache, blockhash, proof, 0);
138 }
139}
140
141BOOST_AUTO_TEST_CASE(winners_tests) {
142 Chainstate &active_chainstate = Assert(m_node.chainman)->ActiveChainstate();
144
145 std::vector<CScript> manualWinners = {
146 CScript() << OP_TRUE,
147 CScript() << OP_FALSE,
148 };
149
150 std::vector<ProofRef> proofs;
151 for (int i = 0; i < 4; i++) {
152 proofs.push_back(
153 buildRandomProof(active_chainstate, MIN_VALID_PROOF_SCORE));
154 }
155
156 // Repeat these tests with multiple block hashes to ensure no unintended
157 // modifications are made to other entries
158 CBlockIndex *pindex = active_chainstate.m_chain.Tip();
159 for (int i = 0; i < 5; i++) {
160 const BlockHash &blockhash = pindex->GetBlockHash();
161 CheckWinners(cache, blockhash, {}, {});
162
163 // Add a winner manually
164 BOOST_CHECK(cache.setWinners(pindex, {manualWinners[0]}));
165 CheckWinners(cache, blockhash, {manualWinners[0]}, {});
166
167 // Before adding contenders, check that vote status is unknown
168 for (int p = 0; p < 4; p++) {
169 CheckVoteStatus(cache, blockhash, proofs[p], -1);
170 }
171
172 // Add some contenders
173 // Local winner
174 BOOST_CHECK(cache.add(pindex, proofs[0],
177 CheckVoteStatus(cache, blockhash, proofs[0], 0);
178
179 // Potential winner other than the local winner
181 cache.add(pindex, proofs[1], StakeContenderStatus::ACCEPTED));
182 CheckVoteStatus(cache, blockhash, proofs[1], 0);
183
184 // Local winner that has been rejected by avalanche so far
186 cache.add(pindex, proofs[2], StakeContenderStatus::IN_WINNER_SET));
187 CheckVoteStatus(cache, blockhash, proofs[2], 1);
188
189 // Some other contender
190 BOOST_CHECK(cache.add(pindex, proofs[3]));
191 CheckVoteStatus(cache, blockhash, proofs[3], 1);
192
193 // Attempting to add duplicates fails, even if status is different than
194 // the successfully added entries.
195 for (const auto &proof : proofs) {
196 BOOST_CHECK(!cache.add(pindex, proof));
198 !cache.add(pindex, proof, StakeContenderStatus::ACCEPTED));
199 BOOST_CHECK(!cache.add(pindex, proof,
203 !cache.add(pindex, proof, StakeContenderStatus::IN_WINNER_SET));
204 }
205
206 CheckWinners(cache, blockhash, {manualWinners[0]},
207 {proofs[0], proofs[2]});
208
209 // Add another manual winner. It always comes before contenders in the
210 // winner set.
211 BOOST_CHECK(cache.setWinners(pindex, manualWinners));
212 CheckWinners(cache, blockhash, manualWinners, {proofs[0], proofs[2]});
213
214 // Adding manual winners with the same payout scripts as contenders in
215 // any state never causes conflicts
216 std::vector<CScript> moreManualWinners = manualWinners;
217 for (const auto &proof : proofs) {
218 moreManualWinners.push_back(proof->getPayoutScript());
219 BOOST_CHECK(cache.setWinners(pindex, moreManualWinners));
220 CheckVoteStatus(cache, blockhash, proof, 0);
221 CheckWinners(cache, blockhash, moreManualWinners,
222 {proofs[0], proofs[2]});
223 }
224 CheckWinners(cache, blockhash, moreManualWinners,
225 {proofs[0], proofs[2]});
226
227 // Avalanche accepting all of the contenders does not change the winners
228 // yet
229 for (const auto &proof : proofs) {
230 cache.accept(StakeContenderId(blockhash, proof->getId()));
231 }
232 CheckWinners(cache, blockhash, moreManualWinners,
233 {proofs[0], proofs[2]});
234
235 // Avalanche rejecting all of the contenders does not change the winners
236 // yet
237 for (const auto &proof : proofs) {
238 cache.reject(StakeContenderId(blockhash, proof->getId()));
239 }
240 CheckWinners(cache, blockhash, moreManualWinners,
241 {proofs[0], proofs[2]});
242
243 // Avalanche finalizing a contender already in the winner set makes no
244 // difference
245 cache.finalize(StakeContenderId(blockhash, proofs[0]->getId()));
246 CheckWinners(cache, blockhash, moreManualWinners,
247 {proofs[0], proofs[2]});
248
249 // Avalanche invalidating a contender not in the winner set makes no
250 // difference
251 cache.invalidate(StakeContenderId(blockhash, proofs[3]->getId()));
252 CheckWinners(cache, blockhash, moreManualWinners,
253 {proofs[0], proofs[2]});
254
255 // Avalanche finalizing a contender that wasn't in the winner set before
256 // makes a new winner
257 cache.finalize(StakeContenderId(blockhash, proofs[1]->getId()));
258 CheckWinners(cache, blockhash, moreManualWinners,
259 {proofs[0], proofs[1], proofs[2]});
260
261 // Avalanche invalidating a contender that was in the winner set removes
262 // it
263 cache.invalidate(StakeContenderId(blockhash, proofs[2]->getId()));
264 CheckWinners(cache, blockhash, moreManualWinners,
265 {proofs[0], proofs[1]});
266
267 pindex = pindex->pprev;
268 }
269
270 // All contenders were added as manual winners at some point in this test,
271 // so reflect that here.
272 for (const auto &proof : proofs) {
273 manualWinners.push_back(proof->getPayoutScript());
274 }
275
276 // Sanity check that past cached state was not poisoned
277 pindex = active_chainstate.m_chain.Tip();
278 for (int i = 0; i < 5; i++) {
279 CheckWinners(cache, pindex->GetBlockHash(), manualWinners,
280 {proofs[0], proofs[1]});
281 for (int p = 0; p < 4; p++) {
282 CheckVoteStatus(cache, pindex->GetBlockHash(), proofs[p], 0);
283 }
284 pindex = pindex->pprev;
285 }
286}
287
288BOOST_AUTO_TEST_CASE(cleanup_tests) {
289 Chainstate &active_chainstate = Assert(m_node.chainman)->ActiveChainstate();
292
293 std::vector<ProofRef> proofs;
294 for (int i = 0; i < 10; i++) {
295 proofs.push_back(
296 buildRandomProof(active_chainstate, MIN_VALID_PROOF_SCORE));
297 }
298
299 CBlockIndex *pindex = active_chainstate.m_chain.Tip();
300 std::vector<BlockHash> blockhashes{pindex->GetBlockHash()};
301 pindex = pindex->pprev;
302 for (int i = 0; i < 3; i++) {
303 BlockHash blockhash = pindex->GetBlockHash();
304 blockhashes.push_back(blockhash);
305 for (const auto &proof : proofs) {
306 cache.add(pindex, proof, StakeContenderStatus::IN_WINNER_SET);
307 }
308 CheckWinners(cache, blockhash, {}, proofs);
309 pindex = pindex->pprev;
310 }
311
312 // Promote up to the height that we will allow cleanup of the cache. Note
313 // that no entries are actually promoted since it uses a dummy peer manager.
314 pindex = active_chainstate.m_chain.Tip()->pprev->pprev->pprev;
315 BOOST_CHECK_EQUAL(pindex->nHeight, 97);
316 cache.promoteToBlock(pindex, pm);
317
318 // Cleaning up nonexistant entries has no impact
319 for (int height : {0, 10, 50, 90, 97}) {
320 cache.cleanup(height);
321 CheckWinners(cache, blockhashes[0], {}, {});
322 CheckWinners(cache, blockhashes[1], {}, proofs);
323 CheckWinners(cache, blockhashes[2], {}, proofs);
324 CheckWinners(cache, blockhashes[3], {}, proofs);
325 }
326
327 // Try to cleanup oldest block in the cache, except promotion at that height
328 // hasn't happened yet so cleanup has no effect.
329 cache.cleanup(98);
330 CheckWinners(cache, blockhashes[0], {}, {});
331 CheckWinners(cache, blockhashes[1], {}, proofs);
332 CheckWinners(cache, blockhashes[2], {}, proofs);
333 CheckWinners(cache, blockhashes[3], {}, proofs);
334
335 // Promote up to that height
336 cache.promoteToBlock(active_chainstate.m_chain.Tip()->pprev->pprev, pm);
337
338 // Cleaning up the oldest block in the cache succeeds now
339 cache.cleanup(98);
340 CheckWinners(cache, blockhashes[0], {}, {});
341 CheckWinners(cache, blockhashes[1], {}, proofs);
342 CheckWinners(cache, blockhashes[2], {}, proofs);
343 CheckWinners(cache, blockhashes[3], {}, {});
344
345 // Add only a local winner to the recently cleared block
346 cache.setWinners(active_chainstate.m_chain.Tip()->pprev->pprev->pprev,
347 {CScript()});
348 CheckWinners(cache, blockhashes[0], {}, {});
349 CheckWinners(cache, blockhashes[1], {}, proofs);
350 CheckWinners(cache, blockhashes[2], {}, proofs);
351 CheckWinners(cache, blockhashes[3], {CScript()}, {});
352
353 // Clean it up again
354 cache.cleanup(98);
355 CheckWinners(cache, blockhashes[0], {}, {});
356 CheckWinners(cache, blockhashes[1], {}, proofs);
357 CheckWinners(cache, blockhashes[2], {}, proofs);
358 CheckWinners(cache, blockhashes[3], {}, {});
359
360 // Add a local winner to a block with winners already there, then clear it
361 cache.setWinners(active_chainstate.m_chain.Tip()->pprev->pprev,
362 {CScript()});
363 CheckWinners(cache, blockhashes[0], {}, {});
364 CheckWinners(cache, blockhashes[1], {}, proofs);
365 CheckWinners(cache, blockhashes[2], {CScript()}, proofs);
366 CheckWinners(cache, blockhashes[3], {}, {});
367
368 cache.promoteToBlock(active_chainstate.m_chain.Tip()->pprev, pm);
369 cache.cleanup(99);
370 CheckWinners(cache, blockhashes[0], {}, {});
371 CheckWinners(cache, blockhashes[1], {}, proofs);
372 CheckWinners(cache, blockhashes[2], {}, {});
373 CheckWinners(cache, blockhashes[3], {}, {});
374
375 // Invalidate proofs so they are no longer in the winner set
376 for (const auto &proof : proofs) {
377 cache.invalidate(StakeContenderId(blockhashes[1], proof->getId()));
378 }
379 CheckWinners(cache, blockhashes[0], {}, {});
380 CheckWinners(cache, blockhashes[1], {}, {});
381 CheckWinners(cache, blockhashes[2], {}, {});
382 CheckWinners(cache, blockhashes[3], {}, {});
383 BOOST_CHECK(!cache.isEmpty());
384
385 // Clean up the remaining block and the cache should be empty now
386 cache.promoteToBlock(active_chainstate.m_chain.Tip(), pm);
387 cache.cleanup(100);
388 BOOST_CHECK(cache.isEmpty());
389 CheckWinners(cache, blockhashes[0], {}, {});
390 CheckWinners(cache, blockhashes[1], {}, {});
391 CheckWinners(cache, blockhashes[2], {}, {});
392 CheckWinners(cache, blockhashes[3], {}, {});
393
394 // Cleaning up again has no effect
395 cache.cleanup(100);
396 BOOST_CHECK(cache.isEmpty());
397 CheckWinners(cache, blockhashes[0], {}, {});
398 CheckWinners(cache, blockhashes[1], {}, {});
399 CheckWinners(cache, blockhashes[2], {}, {});
400 CheckWinners(cache, blockhashes[3], {}, {});
401
402 // Add winners back with random states and sanity check that higher heights
403 // clear the cache as we expect.
404 for (int height : {102, 200, 1000, 1000000}) {
405 pindex = active_chainstate.m_chain.Tip()->pprev;
406 for (size_t i = 1; i < 3; i++) {
407 for (const auto &proof : proofs) {
408 cache.add(pindex, proof, InsecureRandBits(2));
409 cache.setWinners(pindex, {CScript()});
410 }
411
412 // Sanity check there are some winners
413 std::vector<CScript> winners;
414 BOOST_CHECK(cache.getWinners(blockhashes[i], winners));
415 BOOST_CHECK(winners.size() >= 1);
416 pindex = pindex->pprev;
417 }
418
419 // Cleaning up the cache at a height higher than any cache entry results
420 // in an empty cache and no winners.
421 cache.cleanup(height);
422 BOOST_CHECK(cache.isEmpty());
423 CheckWinners(cache, blockhashes[0], {}, {});
424 CheckWinners(cache, blockhashes[1], {}, {});
425 CheckWinners(cache, blockhashes[2], {}, {});
426 CheckWinners(cache, blockhashes[3], {}, {});
427 }
428
429 // But note that the cache will never cleanup higher than the last promoted
430 // block.
431 cache.add(active_chainstate.m_chain.Tip(), proofs[0],
433 for (int height : {102, 200, 1000, 1000000}) {
434 cache.cleanup(height);
435 CheckWinners(cache, blockhashes[0], {}, {proofs[0]});
436 CheckWinners(cache, blockhashes[1], {}, {});
437 CheckWinners(cache, blockhashes[2], {}, {});
438 CheckWinners(cache, blockhashes[3], {}, {});
439 }
440}
441
442BOOST_FIXTURE_TEST_CASE(promote_tests, PeerManagerFixture) {
443 Chainstate &active_chainstate = Assert(m_node.chainman)->ActiveChainstate();
445
447 std::vector<ProofRef> proofs;
448 for (size_t i = 0; i < 3; i++) {
449 auto proof = buildRandomProof(active_chainstate, MIN_VALID_PROOF_SCORE);
450 proofs.push_back(proof);
451 const ProofId &proofid = proof->getId();
452
453 // Register the proof so that it is a peer
454 BOOST_CHECK(pm.registerProof(proof));
455 pm.addNode(0, proofid);
456 BOOST_CHECK(pm.isBoundToPeer(proofid));
457
458 // Our peers also have this proof
459 pm.saveRemoteProof(proofid, 0, true);
460 }
461
462 CBlockIndex *pindex = active_chainstate.m_chain.Tip();
463 const CBlockIndex *tip = pindex;
464 std::vector<BlockHash> blockhashes;
465 for (size_t i = 0; i < 3; i++) {
466 blockhashes.push_back(pindex->GetBlockHash());
467 pindex = pindex->pprev;
468 }
469
470 // Add one proof each to the cache for some early blocks
471 for (size_t i = 0; i < 3; i++) {
472 BlockHash blockhash = pindex->GetBlockHash();
473 blockhashes.push_back(blockhash);
474 cache.add(pindex, proofs[i], StakeContenderStatus::IN_WINNER_SET);
475 CheckWinners(cache, blockhash, {}, {proofs[i]});
476 pindex = pindex->pprev;
477 }
478
479 // Attempting to cleanup the cache before promotion has occurred has no
480 // effect.
481 for (int height = 95; height <= 100; height++) {
482 cache.cleanup(height);
483 CheckWinners(cache, blockhashes[0], {}, {});
484 CheckWinners(cache, blockhashes[1], {}, {});
485 CheckWinners(cache, blockhashes[2], {}, {});
486 CheckWinners(cache, blockhashes[3], {}, {proofs[0]});
487 CheckWinners(cache, blockhashes[4], {}, {proofs[1]});
488 CheckWinners(cache, blockhashes[5], {}, {proofs[2]});
489 }
490
491 // Promote contenders, but they are not winners at that block yet
492 cache.promoteToBlock(tip->pprev->pprev, pm);
493 CheckWinners(cache, blockhashes[0], {}, {});
494 CheckWinners(cache, blockhashes[1], {}, {});
495 CheckWinners(cache, blockhashes[2], {}, {});
496 for (auto &proof : proofs) {
497 // Contenders are unknown for blocks with no cache entries
498 CheckVoteStatus(cache, blockhashes[0], proof, -1);
499 CheckVoteStatus(cache, blockhashes[1], proof, -1);
500 // Contenders are not winners yet at the promoted block
501 CheckVoteStatus(cache, blockhashes[2], proof, 1);
502 }
503
504 // The contenders are still winners for their respective blocks
505 CheckWinners(cache, blockhashes[3], {}, {proofs[0]});
506 CheckWinners(cache, blockhashes[4], {}, {proofs[1]});
507 CheckWinners(cache, blockhashes[5], {}, {proofs[2]});
508
509 // Cleaning up the cache leaves most recent promoted entries alone
510 cache.cleanup(98);
511 CheckWinners(cache, blockhashes[0], {}, {});
512 CheckWinners(cache, blockhashes[1], {}, {});
513 CheckWinners(cache, blockhashes[2], {}, {});
514 for (auto &proof : proofs) {
515 // Contenders are unknown for blocks with no cache entries
516 CheckVoteStatus(cache, blockhashes[0], proof, -1);
517 CheckVoteStatus(cache, blockhashes[1], proof, -1);
518 // Contenders at the promoted block are rejected
519 CheckVoteStatus(cache, blockhashes[2], proof, 1);
520 }
521 CheckWinners(cache, blockhashes[3], {}, {});
522 CheckWinners(cache, blockhashes[4], {}, {});
523 CheckWinners(cache, blockhashes[5], {}, {});
524
525 // Finalize those proofs
526 for (auto &proof : proofs) {
527 cache.finalize(StakeContenderId(blockhashes[2], proof->getId()));
528 // Contenders are unknown for blocks with no cache entries
529 CheckVoteStatus(cache, blockhashes[0], proof, -1);
530 CheckVoteStatus(cache, blockhashes[1], proof, -1);
531 // Contenders at the promoted block are now accepted
532 CheckVoteStatus(cache, blockhashes[2], proof, 0);
533 }
534 CheckWinners(cache, blockhashes[0], {}, {});
535 CheckWinners(cache, blockhashes[1], {}, {});
536 CheckWinners(cache, blockhashes[2], {}, proofs);
537
538 // Now advance the tip and invalidate a proof
539 pm.rejectProof(proofs[2]->getId(),
541 cache.promoteToBlock(tip->pprev, pm);
542 for (auto &proof : proofs) {
543 // Contenders are unknown for blocks with no cache entries
544 CheckVoteStatus(cache, blockhashes[0], proof, -1);
545 }
546 CheckVoteStatus(cache, blockhashes[1], proofs[0], 1);
547 CheckVoteStatus(cache, blockhashes[1], proofs[1], 1);
548 CheckVoteStatus(cache, blockhashes[1], proofs[2], -1);
549
550 // Make the other proofs dangling
551 pm.removeNode(0);
552 SetMockTime(GetTime() + 15 * 60);
553 std::unordered_set<ProofRef, SaltedProofHasher> registeredProofs;
554 pm.cleanupDanglingProofs(registeredProofs);
555 BOOST_CHECK(pm.isDangling(proofs[0]->getId()));
556 BOOST_CHECK(pm.isDangling(proofs[1]->getId()));
557
558 // Re-add those proofs as remote proofs
559 pm.saveRemoteProof(proofs[0]->getId(), 0, true);
560 pm.saveRemoteProof(proofs[1]->getId(), 0, true);
561
562 // Dangling remote proofs still promote like peers do
563 cache.promoteToBlock(tip, pm);
564 CheckVoteStatus(cache, blockhashes[0], proofs[0], 1);
565 CheckVoteStatus(cache, blockhashes[0], proofs[1], 1);
566 CheckVoteStatus(cache, blockhashes[0], proofs[2], -1);
567
568 // But they aren't winners yet and that's expected
569 CheckWinners(cache, blockhashes[0], {}, {});
570}
571
572BOOST_AUTO_TEST_SUITE_END()
ArgsManager gArgs
Definition: args.cpp:38
#define Assert(val)
Identity function.
Definition: check.h:84
void ForceSetArg(const std::string &strArg, const std::string &strValue)
Definition: args.cpp:597
void ClearForcedArg(const std::string &strArg)
Remove a forced arg setting, used only in testing.
Definition: args.cpp:648
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:25
CBlockIndex * pprev
pointer to the index of the predecessor of this block
Definition: blockindex.h:32
BlockHash GetBlockHash() const
Definition: blockindex.h:146
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: blockindex.h:38
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
Definition: chain.h:150
Chainstate stores and provides an API to update our local knowledge of the current best chain.
Definition: validation.h:699
CChain m_chain
The current chain of blockheaders we consult and build on.
Definition: validation.h:808
bool removeNode(NodeId nodeid)
bool isDangling(const ProofId &proofid) const
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
Definition: peermanager.cpp:31
bool isBoundToPeer(const ProofId &proofid) const
bool saveRemoteProof(const ProofId &proofid, const NodeId nodeid, const bool present)
bool rejectProof(const ProofId &proofid, RejectionMode mode=RejectionMode::DEFAULT)
void cleanupDanglingProofs(std::unordered_set< ProofRef, SaltedProofHasher > &registeredProofs)
bool registerProof(const ProofRef &proof, ProofRegistrationState &registrationState, RegistrationMode mode=RegistrationMode::DEFAULT)
const ProofId & getId() const
Definition: proof.h:169
Cache to track stake contenders for recent blocks.
bool invalidate(const StakeContenderId &contenderId)
bool accept(const StakeContenderId &contenderId)
Helpers to set avalanche state of a contender.
void cleanup(const int requestedMinHeight)
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.
int getVoteStatus(const StakeContenderId &contenderId, BlockHash &prevblockhashout) const
Get contender acceptance state for avalanche voting.
bool finalize(const StakeContenderId &contenderId)
bool getWinners(const BlockHash &prevblockhash, std::vector< CScript > &payouts) const
Get payout scripts of the winning proofs.
void promoteToBlock(const CBlockIndex *activeTip, PeerManager &pm)
Promote cache entries to a the active chain tip.
static constexpr Amount PROOF_DUST_THRESHOLD
Minimum amount per utxo.
Definition: proof.h:40
ProofRef buildRandomProof(Chainstate &active_chainstate, uint32_t score, int height, const CKey &masterKey)
Definition: util.cpp:20
constexpr uint32_t MIN_VALID_PROOF_SCORE
Definition: util.h:17
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:259
NodeContext & m_node
Definition: interfaces.cpp:785
#define BOOST_CHECK_EQUAL(v1, v2)
Definition: object.cpp:18
#define BOOST_CHECK(expr)
Definition: object.cpp:17
@ OP_FALSE
Definition: script.h:50
@ OP_TRUE
Definition: script.h:57
static void CheckVoteStatus(StakeContenderCache &cache, const BlockHash &prevblockhash, const ProofRef &proof, int expected)
BOOST_FIXTURE_TEST_CASE(promote_tests, PeerManagerFixture)
static void CheckWinners(StakeContenderCache &cache, const BlockHash &prevblockhash, std::vector< CScript > manualWinners, std::vector< ProofRef > avalancheWinners)
BOOST_AUTO_TEST_CASE(vote_status_tests)
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
double ComputeProofRewardRank(uint32_t proofScore)
To make sure the selection is properly weighted according to the proof score, we normalize the conten...
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:109
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
Definition: time.cpp:89