23#include <validation.h>
26#include <test/util/net.h>
27#include <test/util/setup_common.h>
29#include <boost/mpl/list.hpp>
30#include <boost/test/unit_test.hpp>
42 struct AvalancheTest {
45 static std::vector<CInv> getInvsForNextPoll(
Processor &p) {
52 return p.peerManager->selectNode());
57 static uint32_t getMinQuorumScore(
const Processor &p) {
61 static double getMinQuorumConnectedScoreRatio(
const Processor &p) {
65 static void clearavaproofsNodeCounter(
Processor &p) {
72 std::make_pair(item, voteRecord));
79 static void setFinalizationTip(
Processor &p,
82 p.finalizationTip = pindex;
85 static void setLocalProofShareable(
Processor &p,
bool shareable) {
91 static void addProofToRecentfinalized(
Processor &p,
94 return p.finalizedItems.insert(proofid));
97 static bool setContenderStatusForLocalWinners(
99 std::vector<StakeContenderId> &pollableContenders) {
104 static void setStakingPreconsensus(
Processor &p,
bool enabled) {
108 static void clearInvsNotWorthPolling(
Processor &p) {
128struct AvalancheProcessorTestingSetup :
public AvalancheTestChain100Setup {
129 AvalancheProcessorTestingSetup() : AvalancheTestChain100Setup() {
130 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
false);
138 new CNode(
id++,
nullptr, addr,
145 node->m_has_all_wanted_services =
149 node->fSuccessfullyConnected =
true;
151 m_connman->AddTestNode(*
node);
160 const uint32_t height = 100;
169 BOOST_CHECK(pb.addUTXO(outpoint, amount, height,
false, key));
174 return m_node.avalanche->withPeerManager(
176 return pm.
addNode(nodeid, proofid);
180 bool addNode(
NodeId nodeid) {
181 auto proof = GetProof();
182 return m_node.avalanche->withPeerManager(
185 pm.
addNode(nodeid, proof->getId());
189 std::array<CNode *, 8> ConnectNodes() {
190 auto proof = GetProof();
193 return pm.registerProof(proof);
195 const ProofId &proofid = proof->getId();
197 std::array<CNode *, 8> nodes;
198 for (
CNode *&n : nodes) {
206 void runEventLoop() { AvalancheTest::runEventLoop(*
m_node.avalanche); }
208 NodeId getSuitableNodeToQuery() {
209 return AvalancheTest::getSuitableNodeToQuery(*
m_node.avalanche);
212 std::vector<CInv> getInvsForNextPoll() {
213 return AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
216 uint64_t getRound()
const {
217 return AvalancheTest::getRound(*
m_node.avalanche);
221 std::vector<avalanche::VoteItemUpdate> &updates,
222 std::string &error) {
229 std::vector<avalanche::VoteItemUpdate> &updates) {
237 return m_node.avalanche->addToReconcile(item);
240 void clearInvsNotWorthPolling() {
241 AvalancheTest::clearInvsNotWorthPolling(*
m_node.avalanche);
245struct BlockProvider {
246 AvalancheProcessorTestingSetup *fixture;
249 BlockProvider(AvalancheProcessorTestingSetup *_fixture)
250 : fixture(_fixture) {}
253 CBlock block = fixture->CreateAndProcessBlock({}, CScript());
257 return Assert(fixture->m_node.chainman)
258 ->m_blockman.LookupBlockIndex(blockHash);
265 std::vector<Vote> buildVotesForItems(uint32_t error,
266 std::vector<CBlockIndex *> &&items) {
267 size_t numItems = items.
size();
269 std::vector<Vote> votes;
270 votes.reserve(numItems);
275 votes.emplace_back(error, item->GetBlockHash());
283 pindex->nStatus = pindex->nStatus.withFailed();
287 return std::get<const CBlockIndex *>(item);
291struct ProofProvider {
292 AvalancheProcessorTestingSetup *fixture;
295 ProofProvider(AvalancheProcessorTestingSetup *_fixture)
296 : fixture(_fixture) {}
299 ProofRef proof = fixture->GetProof();
300 fixture->m_node.avalanche->withPeerManager(
308 return proof->
getId();
311 std::vector<Vote> buildVotesForItems(uint32_t error,
312 std::vector<ProofRef> &&items) {
313 size_t numItems = items.
size();
315 std::vector<Vote> votes;
316 votes.reserve(numItems);
320 for (
auto &item : items) {
321 votes.emplace_back(error, item->getId());
327 void invalidateItem(
const ProofRef &proof) {
328 fixture->m_node.avalanche->withPeerManager(
337 return std::get<const ProofRef>(item);
341struct StakeContenderProvider {
342 AvalancheProcessorTestingSetup *fixture;
344 std::vector<avalanche::VoteItemUpdate> updates;
347 StakeContenderProvider(AvalancheProcessorTestingSetup *_fixture)
348 : fixture(_fixture) {}
355 std::vector<CScript> winners;
356 if (!fixture->m_node.avalanche->getStakingRewardWinners(
360 const ProofRef proofWinner = fixture->GetProof();
362 fixture->m_node.avalanche->setStakingRewardWinners(chaintip,
367 const ProofRef proof = fixture->GetProof();
371 fixture->m_node.avalanche->withPeerManager(
378 fixture->m_node.avalanche->acceptStakeContender(contenderId);
380 BOOST_CHECK(fixture->m_node.avalanche->getStakeContenderStatus(
390 buildVotesForItems(uint32_t error, std::vector<StakeContenderId> &&items) {
391 size_t numItems = items.
size();
393 std::vector<Vote> votes;
394 votes.reserve(numItems);
397 std::sort(items.begin(), items.end(),
401 for (
auto &item : items) {
402 votes.emplace_back(error, item);
409 fixture->m_node.avalanche->rejectStakeContender(contenderId);
417 AvalancheTest::removeVoteRecord(*(fixture->m_node.avalanche),
422 return std::get<const StakeContenderId>(item);
427 AvalancheProcessorTestingSetup *fixture;
429 std::vector<avalanche::VoteItemUpdate> updates;
432 TxProvider(AvalancheProcessorTestingSetup *_fixture) : fixture(_fixture) {}
442 TestMemPoolEntryHelper mempoolEntryHelper;
443 auto entry = mempoolEntryHelper.Fee(1000 *
SATOSHI).FromTx(tx);
459 std::vector<Vote> buildVotesForItems(uint32_t error,
460 std::vector<CTransactionRef> &&items) {
461 size_t numItems = items.
size();
463 std::vector<Vote> votes;
464 votes.reserve(numItems);
467 std::sort(items.begin(), items.end(),
469 return lhs->GetId() < rhs->GetId();
471 for (
auto &item : items) {
472 votes.emplace_back(error, item->GetId());
488 return std::get<const CTransactionRef>(item);
494BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheProcessorTestingSetup)
498 StakeContenderProvider, TxProvider>;
500 boost::mpl::list<BlockProvider, ProofProvider, TxProvider>;
509 std::set<VoteStatus> status{
510 VoteStatus::Invalid, VoteStatus::Rejected, VoteStatus::Accepted,
511 VoteStatus::Finalized, VoteStatus::Stale,
514 auto item = provider.buildVoteItem();
516 for (
auto s : status) {
539 auto item = provider.buildVoteItem();
540 auto itemid = provider.getVoteItemId(item);
549 auto avanodes = ConnectNodes();
551 int nextNodeIndex = 0;
552 std::vector<avalanche::VoteItemUpdate> updates;
553 auto registerNewVote = [&](
const Response &resp) {
555 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
560 auto finalize = [&](
const auto finalizeItemId) {
561 Response resp = {getRound(), 0, {
Vote(0, finalizeItemId)}};
563 registerNewVote(next(resp));
564 if (updates.size() > 0) {
569 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
570 m_node.avalanche->setRecentlyFinalized(finalizeItemId);
577 auto finalizeNewItem = [&]() {
578 auto anotherItem = provider.buildVoteItem();
580 auto anotherItemId = provider.getVoteItemId(anotherItem);
583 AvalancheTest::addVoteRecord(*
m_node.avalanche, anotherVoteItem,
585 finalize(anotherItemId);
605 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
618 auto item =
decltype(provider.buildVoteItem())();
625 item = provider.buildVoteItem();
636 auto itemZero =
decltype(provider.buildVoteItem())();
649 auto item = provider.buildVoteItem();
659 const uint32_t invType = provider.invType;
661 auto item = provider.buildVoteItem();
662 auto itemid = provider.getVoteItemId(item);
665 auto avanodes = ConnectNodes();
673 auto invs = getInvsForNextPoll();
681 int nextNodeIndex = 0;
682 std::vector<avalanche::VoteItemUpdate> updates;
683 auto registerNewVote = [&](
const Response &resp) {
685 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
691 for (
int i = 0; i < 6; i++) {
692 registerNewVote(next(resp));
699 resp = {getRound(), 0, {
Vote(-1, itemid)}};
700 registerNewVote(next(resp));
705 resp = {getRound(), 0, {
Vote(0, itemid)}};
706 for (
int i = 1; i < 7; i++) {
707 registerNewVote(next(resp));
714 resp = {getRound(), 0, {
Vote(-1, itemid)}};
715 registerNewVote(next(resp));
719 registerNewVote(next(resp));
724 resp = {getRound(), 0, {
Vote(0, itemid)}};
725 for (
int i = 2; i < 8; i++) {
726 registerNewVote(next(resp));
734 registerNewVote(next(resp));
741 invs = getInvsForNextPoll();
747 registerNewVote(next(resp));
749 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
750 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
753 invs = getInvsForNextPoll();
757 item = provider.buildVoteItem();
758 itemid = provider.getVoteItemId(item);
762 invs = getInvsForNextPoll();
767 resp = {getRound(), 0, {
Vote(1, itemid)}};
768 for (
int i = 0; i < 6; i++) {
769 registerNewVote(next(resp));
775 registerNewVote(next(resp));
778 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
779 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
783 registerNewVote(next(resp));
789 invs = getInvsForNextPoll();
795 registerNewVote(next(resp));
798 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
799 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
802 invs = getInvsForNextPoll();
808 const uint32_t invType = provider.invType;
810 auto itemA = provider.buildVoteItem();
811 auto itemidA = provider.getVoteItemId(itemA);
813 auto itemB = provider.buildVoteItem();
814 auto itemidB = provider.getVoteItemId(itemB);
817 auto avanodes = ConnectNodes();
825 auto invs = getInvsForNextPoll();
830 uint64_t round = getRound();
832 std::vector<avalanche::VoteItemUpdate> updates;
834 {round, 0, {
Vote(0, itemidA)}}, updates));
838 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
841 invs = getInvsForNextPoll();
845 for (
size_t i = 0; i < invs.size(); i++) {
851 for (
int i = 0; i < 4; i++) {
852 NodeId nodeid = getSuitableNodeToQuery();
854 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
860 NodeId nodeid = getSuitableNodeToQuery();
862 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
868 NodeId firstNodeid = getSuitableNodeToQuery();
870 NodeId secondNodeid = getSuitableNodeToQuery();
876 BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates));
878 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemA);
879 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
882 invs = getInvsForNextPoll();
888 BOOST_CHECK(registerVotes(secondNodeid, resp, updates));
890 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemB);
891 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
894 invs = getInvsForNextPoll();
900 const uint32_t invType = provider.invType;
902 auto item = provider.buildVoteItem();
903 auto itemid = provider.getVoteItemId(item);
910 std::set<NodeId> avanodeIds;
911 auto avanodes = ConnectNodes();
912 for (
auto avanode : avanodes) {
914 avanodeIds.insert(avanode->GetId());
917 auto getSelectedAvanodeId = [&]() {
918 NodeId avanodeid = getSuitableNodeToQuery();
919 BOOST_CHECK(avanodeIds.find(avanodeid) != avanodeIds.end());
924 NodeId avanodeid = getSelectedAvanodeId();
928 auto invs = getInvsForNextPoll();
933 std::set<NodeId> unselectedNodeids = avanodeIds;
934 unselectedNodeids.erase(avanodeid);
935 const size_t remainingNodeIds = unselectedNodeids.size();
937 uint64_t round = getRound();
938 for (
size_t i = 0; i < remainingNodeIds; i++) {
943 NodeId nodeid = getSuitableNodeToQuery();
944 BOOST_CHECK(unselectedNodeids.find(nodeid) != avanodeIds.end());
945 unselectedNodeids.erase(nodeid);
955 std::vector<avalanche::VoteItemUpdate> updates;
956 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
963 auto checkRegisterVotesError = [&](
NodeId nodeid,
965 const std::string &expectedError) {
973 checkRegisterVotesError(avanodeid, next(resp),
"unexpected-ava-response");
982 resp = {round, 0, {
Vote(0, itemid),
Vote(0, itemid)}};
984 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
988 resp = {getRound(), 0, {}};
990 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
994 resp = {getRound(), 0, {
Vote()}};
996 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1003 invs = getInvsForNextPoll();
1006 item = provider.buildVoteItem();
1007 itemid = provider.getVoteItemId(item);
1010 invs = getInvsForNextPoll();
1014 uint64_t queryRound = getRound();
1017 resp = {queryRound + 1, 0, {
Vote()}};
1018 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1020 resp = {queryRound - 1, 0, {
Vote()}};
1021 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1025 resp = {queryRound, 0, {
Vote(0, itemid)}};
1026 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1029 resp = {queryRound, 0, {
Vote(0, itemid)}};
1030 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1035 const auto item2 = provider.buildVoteItem();
1038 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1039 resp = {getRound(), 0, {votes[1], votes[0]}};
1041 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1045 resp = {getRound(), 0, votes};
1047 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1054 const uint32_t invType = provider.invType;
1056 auto itemA = provider.buildVoteItem();
1057 auto itemB = provider.buildVoteItem();
1059 auto avanodes = ConnectNodes();
1060 int nextNodeIndex = 0;
1063 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1069 auto invs = getInvsForNextPoll();
1071 for (
size_t i = 0; i < invs.size(); i++) {
1077 provider.invalidateItem(itemB);
1079 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1080 std::vector<avalanche::VoteItemUpdate> updates;
1083 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1084 goodResp, updates));
1088 invs = getInvsForNextPoll();
1091 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1094 Response badResp{getRound(), 0, votes};
1098 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1099 badResp, updates, error));
1103 votes = provider.buildVotesForItems(1, {itemA});
1104 auto registerNewVote = [&]() {
1105 Response resp = {getRound(), 0, votes};
1107 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1108 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1110 for (
size_t i = 0; i < 4000; i++) {
1112 if (updates.size() > 0 &&
1113 updates[0].getStatus() == VoteStatus::Invalid) {
1119 invs = getInvsForNextPoll();
1123 badResp =
Response(getRound(), 0, votes);
1126 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1127 badResp, updates, error));
1131BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1136 auto queryTimeDuration = std::chrono::milliseconds(10);
1137 setArg(
"-avatimeout",
ToString(queryTimeDuration.count()));
1139 setArg(
"-avalanchestakingpreconsensus",
"0");
1142 m_node.avalanche = Processor::MakeProcessor(
1146 const auto item = provider.buildVoteItem();
1147 const auto itemid = provider.getVoteItemId(item);
1157 for (
int i = 0; i < 10; i++) {
1159 avanodeid = getSuitableNodeToQuery();
1161 auto start = Now<SteadyMilliseconds>();
1165 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1168 std::vector<avalanche::VoteItemUpdate> updates;
1169 bool ret = registerVotes(avanodeid, next(resp), updates);
1170 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1181 avanodeid = getSuitableNodeToQuery();
1185 std::this_thread::sleep_for(queryTimeDuration);
1187 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1193 const uint32_t invType = provider.invType;
1196 auto proof = GetProof();
1200 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1201 for (
auto &n : nodes) {
1207 const auto item = provider.buildVoteItem();
1208 const auto itemid = provider.getVoteItemId(item);
1212 std::map<NodeId, uint64_t> node_round_map;
1214 NodeId nodeid = getSuitableNodeToQuery();
1215 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1216 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1217 auto invs = getInvsForNextPoll();
1225 auto suitablenodeid = getSuitableNodeToQuery();
1227 auto invs = getInvsForNextPoll();
1233 auto it = node_round_map.begin();
1235 std::vector<avalanche::VoteItemUpdate> updates;
1236 BOOST_CHECK(registerVotes(it->first, resp, updates));
1237 node_round_map.erase(it);
1239 invs = getInvsForNextPoll();
1246 std::vector<VoteItemUpdate> updates;
1248 CBlock block = CreateAndProcessBlock({}, CScript());
1254 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1258 auto avanodes = ConnectNodes();
1267 uint64_t round = getRound();
1271 for (
size_t i = 0; i < avanodes.size(); i++) {
1273 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1277 const NodeId firstNodeId = getSuitableNodeToQuery();
1278 std::map<NodeId, uint64_t> node_round_map;
1280 for (
size_t i = 0; i < avanodes.size(); i++) {
1281 NodeId nodeid = getSuitableNodeToQuery();
1282 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1283 node_round_map[nodeid] = getRound();
1289 auto confidence =
m_node.avalanche->getConfidence(pindex);
1290 BOOST_REQUIRE(confidence > 0);
1292 for (
auto &[nodeid, r] : node_round_map) {
1293 if (nodeid == firstNodeId) {
1300 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1305 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1312 CBlock block = CreateAndProcessBlock({}, CScript());
1318 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1325 std::chrono::steady_clock::time_point start,
stop;
1335 auto avanodes = ConnectNodes();
1338 NodeId nodeid = getSuitableNodeToQuery();
1339 BOOST_CHECK_NE(nodeid,
NO_NODE);
1342 uint64_t queryRound = getRound();
1346 for (
int i = 0; i < 60 * 1000; i++) {
1350 if (getRound() == queryRound + avanodes.size()) {
1359 uint64_t responseRound = getRound();
1360 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1362 std::vector<VoteItemUpdate> updates;
1364 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1367 for (
int i = 0; i < 10000; i++) {
1370 if (getRound() != responseRound) {
1371 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1390 schedulerThread.join();
1395 std::chrono::steady_clock::time_point start,
stop;
1397 std::thread schedulerThread;
1407 m_node.avalanche.reset();
1414 schedulerThread.join();
1421 auto addProofToReconcile = [&](uint32_t proofScore) {
1431 auto proof = addProofToReconcile(++score);
1433 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1442 for (
size_t i = 0; i < 10; i++) {
1443 auto proof = addProofToReconcile(++score);
1445 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1450 lastProofId = proof->
getId();
1453 for (
size_t i = 0; i < 10; i++) {
1454 auto proof = addProofToReconcile(--score);
1456 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1464 auto proof = addProofToReconcile(--score);
1465 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1466 for (
auto &inv : invs) {
1467 BOOST_CHECK_NE(inv.hash, proof->
getId());
1473 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1474 setArg(
"-avalancheconflictingproofcooldown",
"0");
1488 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1489 coins.
AddCoin(conflictingOutpoint,
1492 coins.
AddCoin(immatureOutpoint,
1497 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1498 uint32_t height = 10) {
1505 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1506 auto validProof = buildProof(conflictingOutpoint, 2);
1507 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1558 int minStake = 400'000'000;
1559 setArg(
"-avaminquorumstake",
ToString(minStake));
1560 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1564 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1572 setArg(
"-avaproof", localProof->ToHex());
1576 m_node.avalanche = Processor::MakeProcessor(
1583 localProof->getId());
1587 AvalancheTest::getMinQuorumConnectedScoreRatio(*
m_node.avalanche), 0.5);
1609 for (
NodeId id = 0;
id < 8;
id++) {
1627 const int64_t tipTime =
1631 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1632 const int height = 100;
1633 const bool isCoinbase =
false;
1640 height, isCoinbase),
1645 auto proof2 = pb.
build();
1656 pm.
addNode(8, proof2->getId());
1675 m_node.avalanche->withPeerManager(
1686 auto spendProofUtxo = [&](
ProofRef proof) {
1699 for (int64_t i = 0; i < 6; i++) {
1701 CreateAndProcessBlock({}, CScript());
1705 ->GetMedianTimePast(),
1706 proof2->getExpirationTime());
1717 spendProofUtxo(proof1);
1724 spendProofUtxo(
m_node.avalanche->getLocalProof());
1736 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1739 {
"",
"",
"",
false},
1740 {
"-1",
"-1",
"-1",
false},
1743 {
"-1",
"0",
"0",
false},
1744 {
"-0.01",
"0",
"0",
false},
1745 {
"21000000000000.01",
"0",
"0",
false},
1748 {
"0",
"-1",
"0",
false},
1749 {
"0",
"1.1",
"0",
false},
1752 {
"0",
"0",
"-1",
false},
1755 {
"0",
"0",
"0",
true},
1756 {
"0.00",
"0",
"0",
true},
1757 {
"0.01",
"0",
"0",
true},
1758 {
"1",
"0.1",
"0",
true},
1759 {
"10",
"0.5",
"0",
true},
1760 {
"10",
"1",
"0",
true},
1761 {
"21000000000000.00",
"0",
"0",
true},
1762 {
"0",
"0",
"1",
true},
1763 {
"0",
"0",
"100",
true},
1768 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1770 setArg(
"-avaminquorumstake", stake);
1771 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1772 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1775 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1795 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1796 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1799 auto processor = Processor::MakeProcessor(
1803 auto addNode = [&](
NodeId nodeid) {
1816 for (
NodeId id = 100;
id < 108;
id++) {
1821 minAvaproofsMessages <= 0);
1823 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1826 processor->avaproofsSent(i);
1830 processor->avaproofsSent(i);
1836 addNode(minAvaproofsMessages);
1837 processor->avaproofsSent(minAvaproofsMessages);
1841 AvalancheTest::clearavaproofsNodeCounter(*processor);
1845 checkMinAvaproofsMessages(0);
1846 checkMinAvaproofsMessages(1);
1847 checkMinAvaproofsMessages(10);
1848 checkMinAvaproofsMessages(100);
1853 setArg(
"-avastalevotethreshold",
1855 setArg(
"-avastalevotefactor",
"2");
1857 setArg(
"-avalanchestakingpreconsensus",
"0");
1859 const std::vector<std::tuple<int, int>> testCases = {
1866 m_node.avalanche = Processor::MakeProcessor(
1875 const uint32_t invType = provider.invType;
1877 const auto item = provider.buildVoteItem();
1878 const auto itemid = provider.getVoteItemId(item);
1881 auto avanodes = ConnectNodes();
1882 int nextNodeIndex = 0;
1884 std::vector<avalanche::VoteItemUpdate> updates;
1885 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
1888 auto invs = getInvsForNextPoll();
1895 auto registerNewVote = [&](
const Response &resp) {
1897 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1898 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1902 for (
int i = 0; i < numYesVotes; i++) {
1904 registerNewVote(next(resp));
1907 i >= 6 ? i - 5 : 0);
1912 for (
int i = 0; i < numNeutralVotes; i++) {
1914 registerNewVote(next(resp));
1919 invs = getInvsForNextPoll();
1926 registerNewVote(next(resp));
1928 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
1929 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
1932 invs = getInvsForNextPoll();
1938 BlockProvider provider(
this);
1942 std::vector<CBlockIndex *> blockIndexes;
1946 blockIndexes.push_back(pindex);
1949 auto invs = getInvsForNextPoll();
1961 std::vector<Vote> votes;
1964 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
1965 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
1968 auto avanodes = ConnectNodes();
1969 int nextNodeIndex = 0;
1971 std::vector<avalanche::VoteItemUpdate> updates;
1972 auto registerNewVote = [&]() {
1973 Response resp = {getRound(), 0, votes};
1975 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1976 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1982 bool eleventhBlockFinalized =
false;
1983 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
1986 for (
auto &update : updates) {
1987 if (update.getStatus() == VoteStatus::Finalized &&
1988 provider.fromAnyVoteItem(update.getVoteItem())
1989 ->GetBlockHash() == eleventhBlockHash) {
1990 eleventhBlockFinalized =
true;
2001 clearInvsNotWorthPolling();
2002 invs = getInvsForNextPoll();
2004 for (
size_t i = 0; i < 10; i++) {
2018 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2020 activeChainstate.InvalidateBlock(state, tip);
2023 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2026 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2034 activeChainstate.ResetBlockFailureFlags(tip);
2036 activeChainstate.ActivateBestChain(state);
2040 clearInvsNotWorthPolling();
2041 invs = getInvsForNextPoll();
2048 for (
auto &inv : invs) {
2049 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2052 bool tipFinalized =
false;
2053 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2056 for (
auto &update : updates) {
2057 if (update.getStatus() == VoteStatus::Finalized &&
2058 provider.fromAnyVoteItem(update.getVoteItem())
2059 ->GetBlockHash() == tiphash) {
2060 tipFinalized =
true;
2069 clearInvsNotWorthPolling();
2070 invs = getInvsForNextPoll();
2078 BlockHash alttiphash = alttip->GetBlockHash();
2079 votes = {{1, alttiphash}};
2081 bool alttipInvalidated =
false;
2082 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2085 for (
auto &update : updates) {
2086 if (update.getStatus() == VoteStatus::Invalid &&
2087 provider.fromAnyVoteItem(update.getVoteItem())
2088 ->GetBlockHash() == alttiphash) {
2089 alttipInvalidated =
true;
2094 invs = getInvsForNextPoll();
2105 const int numberElementsEachType = 100;
2108 std::vector<ProofRef> proofs;
2109 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2113 proofs.emplace_back(std::move(proof));
2115 Shuffle(proofs.begin(), proofs.end(), rng);
2117 std::vector<CBlockIndex> indexes;
2118 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2121 indexes.emplace_back(std::move(index));
2123 Shuffle(indexes.begin(), indexes.end(), rng);
2125 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2126 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2132 for (
size_t i = 0; i < numberElementsEachType; i++) {
2134 const size_t firstType = rng.
randrange(numTypes);
2136 for (
size_t j = 0; j < numTypes; j++) {
2137 switch ((firstType + j) % numTypes) {
2140 writeView->insert(std::make_pair(
2141 std::get<0>(allItems)[i],
VoteRecord(
true)));
2145 writeView->insert(std::make_pair(
2146 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2157 auto readView = voteMap.getReadView();
2158 auto it = readView.begin();
2161 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2162 for (
size_t i = 0; i < numberElementsEachType; i++) {
2163 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2165 uint32_t currentScore =
2166 std::get<const ProofRef>(it->first)->getScore();
2167 BOOST_CHECK_LT(currentScore, lastScore);
2168 lastScore = currentScore;
2176 for (
size_t i = 0; i < numberElementsEachType; i++) {
2177 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2180 std::get<const CBlockIndex *>(it->first)->nChainWork;
2182 lastWork = currentWork;
2195 const auto block = std::make_shared<const CBlock>(
2196 this->CreateBlock({}, CScript(), chainstate));
2223 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
2236 auto now = GetTime<std::chrono::seconds>();
2242 std::vector<CScript> winners;
2245 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2250 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2255 prevBlock.
nTime = now.count();
2260 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2263 size_t numProofs = 10;
2264 std::vector<ProofRef> proofs;
2265 proofs.reserve(numProofs);
2266 for (
size_t i = 0; i < numProofs; i++) {
2270 auto proof = GetProof(payoutScript);
2276 return pm.setFinalized(peer.peerid);
2280 proofs.emplace_back(std::move(proof));
2288 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2291 auto winnerExists = [&](
const CScript &expectedWinner) {
2292 const std::string winnerString =
FormatScript(expectedWinner);
2294 for (
const ProofRef &proof : proofs) {
2305 prevBlock.
nTime = now.count();
2310 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2316 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2322 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2326 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2331 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2335 m_node.avalanche->cleanupStakingRewards(101);
2339 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2343 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2349 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2353 m_node.avalanche->cleanupStakingRewards(200);
2357 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2359 !
m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2371 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2377 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2385 auto localProof = buildProof(outpoint, 1, 100);
2388 setArg(
"-avaproof", localProof->ToHex());
2389 setArg(
"-avalancheconflictingproofcooldown",
"0");
2390 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2391 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2395 m_node.avalanche = Processor::MakeProcessor(
2400 localProof->getId());
2402 auto checkLocalProofState = [&](
const bool boundToPeer,
2407 return pm.isBoundToPeer(localProof->getId());
2410 BOOST_CHECK_MESSAGE(
2411 m_node.avalanche->getLocalProofRegistrationState().GetResult() ==
2413 m_node.avalanche->getLocalProofRegistrationState().ToString());
2420 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2424 AvalancheTest::setLocalProofShareable(*
m_node.avalanche,
true);
2426 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2427 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2431 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2432 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2436 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2440 auto conflictingProof = buildProof(outpoint, 2, 100);
2446 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2447 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2451 setArg(
"-avalancheconflictingproofcooldown",
"0");
2452 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2472 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2479 auto proof = buildProof(outpoint, 1);
2498 AvalancheTest::addProofToRecentfinalized(*
m_node.avalanche, proof->
getId());
2505 return peer.hasFinalized;
2512 auto betterProof = buildProof(outpoint, 2);
2535 m_node.avalanche = Processor::MakeProcessor(
2541 auto now = GetTime<std::chrono::seconds>();
2544 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
true);
2552 const ProofId proofid1 = proof1->getId();
2557 const ProofId proofid2 = proof2->getId();
2568 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2570 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2576 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2581 for (
NodeId n = 0; n < 8; n++) {
2586 return pm.setFinalized(peer.peerid);
2595 CBlock block = CreateAndProcessBlock({}, CScript());
2598 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2599 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2605 std::vector<CScript> winners;
2609 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2614 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2618 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2620 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2626 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2632 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2640 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2643 m_node.avalanche->getStakeContenderStatus(contender1_block1), -1);
2645 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2648 m_node.avalanche->getStakeContenderStatus(contender2_block1), -1);
2650 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2653 m_node.avalanche->setStakingRewardWinners(
2654 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2659 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2662 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2665 m_node.avalanche->withPeerManager(
2671 const ProofId proofid3 = proof3->getId();
2674 for (
NodeId n = 0; n < 8; n++) {
2680 block = CreateAndProcessBlock({}, CScript());
2683 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2684 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2688 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2692 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2694 m_node.avalanche->getStakeContenderStatus(contender2_block2), -1);
2701 m_node.avalanche->getStakeContenderStatus(contender1_block3), -1);
2705 m_node.avalanche->getStakeContenderStatus(contender2_block3), -1);
2708 m_node.avalanche->withPeerManager(
2712 size_t numProofs = 8;
2713 std::vector<ProofRef> proofs;
2714 proofs.reserve(numProofs);
2715 for (
size_t i = 0; i < numProofs; i++) {
2724 return pm.setFinalized(peer.peerid);
2727 proofs.emplace_back(std::move(proof));
2732 const ProofId proofid = proofs[0]->getId();
2733 for (
NodeId n = 0; n < 8; n++) {
2743 std::vector<CScript> winners;
2744 for (
int attempt = 0; attempt < 10; attempt++) {
2746 block = CreateAndProcessBlock({}, CScript());
2749 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2750 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2756 chaintip->GetBlockHash(), winners));
2757 if (winners.size() == 8) {
2765 size_t numAccepted = 0;
2766 for (
const auto &proof : proofs) {
2770 if (
m_node.avalanche->getStakeContenderStatus(contender) == 0) {
2772 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2780 block = CreateAndProcessBlock({}, CScript());
2783 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2788 m_node.avalanche->withPeerManager(
2790 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2799 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2800 bestproof->getPayoutScript()) == winners.end());
2807 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2818 block = CreateAndProcessBlock({}, CScript());
2821 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2822 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2823 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
2830 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2844 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2845 bestproof->getPayoutScript()) == winners.end());
2853 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2864 auto now = GetTime<std::chrono::seconds>();
2868 auto localWinnerProof =
2870 ProofId localWinnerProofId = localWinnerProof->getId();
2872 localWinnerProof->getId());
2881 for (
NodeId n = 0; n < 8; n++) {
2882 pm.
addNode(n, localWinnerProofId);
2885 return pm.setFinalized(peer.peerid);
2892 chaintip->
nTime = now.count();
2898 std::vector<ProofRef> acceptedContenderProofs;
2899 acceptedContenderProofs.push_back(localWinnerProof);
2906 for (
size_t numContenders = 2;
2910 m_node.avalanche->withPeerManager(
2916 if (rank <= bestRank) {
2918 acceptedContenderProofs.push_back(proof);
2919 const size_t numAccepted =
2921 acceptedContenderProofs.size());
2922 std::sort(acceptedContenderProofs.begin(),
2923 acceptedContenderProofs.begin() + numAccepted,
2925 const ProofId leftProofId = left->getId();
2926 const ProofId rightProofId = right->getId();
2927 const StakeContenderId leftContenderId(chaintipHash,
2929 const StakeContenderId rightContenderId(chaintipHash,
2931 return RewardRankComparator()(
2933 leftContenderId.ComputeProofRewardRank(
2934 MIN_VALID_PROOF_SCORE),
2935 leftProofId, rightContenderId,
2936 rightContenderId.ComputeProofRewardRank(
2937 MIN_VALID_PROOF_SCORE),
2942 std::vector<StakeContenderId> pollableContenders;
2943 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
2944 *
m_node.avalanche, chaintip, pollableContenders));
2946 pollableContenders.size(),
2951 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
2955 chaintipHash, acceptedContenderProofs[i]->getId());
2957 std::find(pollableContenders.begin(), pollableContenders.end(),
2958 acceptedContenderId) != pollableContenders.end());
2960 m_node.avalanche->getStakeContenderStatus(acceptedContenderId),
2965 std::set<StakeContenderId> unacceptedContenderIds(
2966 pollableContenders.begin(), pollableContenders.end());
2967 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
2969 chaintipHash, acceptedContenderProof->getId());
2970 unacceptedContenderIds.erase(acceptedContenderId);
2973 for (
auto cid : unacceptedContenderIds) {
2980 m_node.avalanche->getStakeContenderStatus(localWinnerContenderId),
2985BOOST_AUTO_TEST_SUITE_END()
static constexpr Amount SATOSHI
static constexpr Amount COIN
uint256 ArithToUint256(const arith_uint256 &a)
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
A CService with information about it as peer.
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
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
const BlockHash * phashBlock
pointer to the hash of the block, if any.
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.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
void AddCoin(const COutPoint &outpoint, Coin coin, bool possible_overwrite)
Add a coin.
bool SpendCoin(const COutPoint &outpoint, Coin *moveto=nullptr)
Spend a coin.
An encapsulated secp256k1 private key.
static CKey MakeCompressedKey()
Produce a valid compressed key.
CPubKey GetPubKey() const
Compute the public key from a private key.
A mutable version of CTransaction.
std::vector< CTxOut > vout
Information about a peer.
Simple class for background tasks that should be run periodically or once "after a while".
void serviceQueue() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Services the queue 'forever'.
size_t getQueueInfo(std::chrono::steady_clock::time_point &first, std::chrono::steady_clock::time_point &last) const EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Returns number of tasks waiting to be serviced, and first and last task times.
void StopWhenDrained() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Tell any threads running serviceQueue to stop when there is no work left to be done.
A combination of a network address (CNetAddr) and a (TCP) port.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
bool exists(const TxId &txid) const
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void addUnchecked(CTxMemPoolEntryRef entry) EXCLUSIVE_LOCKS_REQUIRED(cs
If sanity-checking is turned on, check makes sure the pool is consistent (does not contain two transa...
An output of a transaction.
Chainstate stores and provides an API to update our local knowledge of the current best chain.
bool ActivateBestChain(BlockValidationState &state, std::shared_ptr< const CBlock > pblock=nullptr, avalanche::Processor *const avalanche=nullptr) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex
Find the best known block, and make it the tip of the block chain.
CChain m_chain
The current chain of blockheaders we consult and build on.
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
bool AcceptBlock(const std::shared_ptr< const CBlock > &pblock, BlockValidationState &state, bool fRequested, const FlatFilePos *dbp, bool *fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Sufficiently validate a block for disk storage (and store on disk).
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
ReadView getReadView() const
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
256-bit unsigned big integer.
bool removeNode(NodeId nodeid)
uint32_t getConnectedPeersScore() const
bool isDangling(const ProofId &proofid) const
bool exists(const ProofId &proofid) const
Return true if the (valid) proof exists, but only for non-dangling proofs.
bool forPeer(const ProofId &proofid, Callable &&func) const
uint32_t getTotalPeersScore() const
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
std::unordered_set< ProofRef, SaltedProofHasher > updatedBlockTip()
Update the peer set when a new block is connected.
bool isBoundToPeer(const ProofId &proofid) const
bool saveRemoteProof(const ProofId &proofid, const NodeId nodeid, const bool present)
bool isImmature(const ProofId &proofid) const
bool rejectProof(const ProofId &proofid, RejectionMode mode=RejectionMode::DEFAULT)
void addStakeContender(const ProofRef &proof)
bool isInConflictingPool(const ProofId &proofid) const
void cleanupDanglingProofs(std::unordered_set< ProofRef, SaltedProofHasher > ®isteredProofs)
bool registerProof(const ProofRef &proof, ProofRegistrationState ®istrationState, RegistrationMode mode=RegistrationMode::DEFAULT)
Mutex cs_finalizedItems
Rolling bloom filter to track recently finalized inventory items of any type.
bool setContenderStatusForLocalWinners(const CBlockIndex *pindex, std::vector< StakeContenderId > &pollableContenders) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Helper to set the vote status for local winners in the contender cache.
std::atomic< uint64_t > round
Keep track of peers and queries sent.
std::vector< CInv > getInvsForNextPoll(RWCollection< VoteMap >::ReadView &voteRecordsReadView, bool forPoll=true) const
void runEventLoop() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
void updatedBlockTip() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
RWCollection< VoteMap > voteRecords
Items to run avalanche on.
uint32_t minQuorumScore
Quorum management.
std::atomic< bool > m_canShareLocalProof
std::atomic< int64_t > avaproofsNodeCounter
std::atomic_bool m_stakingPreConsensus
Mutex cs_peerManager
Keep track of the peers and associated infos.
void clearInvsNotWorthPolling() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
double minQuorumConnectedScoreRatio
bool addUTXO(COutPoint utxo, Amount amount, uint32_t height, bool is_coinbase, CKey key)
const CScript & getPayoutScript() const
const ProofId & getId() const
const std::vector< SignedStake > & getStakes() const
uint32_t getCooldown() const
const std::vector< Vote > & GetVotes() const
uint64_t getRound() const
const AnyVoteItem & getVoteItem() const
const VoteStatus & getStatus() const
static constexpr unsigned int size()
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
static const uint256 ZERO
@ OUTBOUND_FULL_RELAY
These are the default connections that we use to connect with the network.
std::string FormatScript(const CScript &script)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
std::string EncodeSecret(const CKey &key)
static constexpr Amount PROOF_DUST_THRESHOLD
Minimum amount per utxo.
std::variant< const ProofRef, const CBlockIndex *, const StakeContenderId, const CTransactionRef > AnyVoteItem
const CScript UNSPENDABLE_ECREG_PAYOUT_SCRIPT
ProofRef buildRandomProof(Chainstate &active_chainstate, uint32_t score, int height, const CKey &masterKey)
constexpr uint32_t MIN_VALID_PROOF_SCORE
std::string ToString(const T &t)
Locale-independent version of std::to_string.
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
static CTransactionRef MakeTransactionRef()
std::shared_ptr< const CTransaction > CTransactionRef
static constexpr size_t AVALANCHE_CONTENDER_MAX_POLLABLE
Maximum number of stake contenders to poll for, leaving room for polling blocks and proofs in the sam...
static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
static constexpr uint32_t AVALANCHE_FINALIZED_ITEMS_FILTER_NUM_ELEMENTS
The size of the finalized items filter.
BOOST_AUTO_TEST_CASE_TEMPLATE(voteitemupdate, P, VoteItemProviders)
BOOST_AUTO_TEST_CASE(quorum_diversity)
boost::mpl::list< BlockProvider, ProofProvider, StakeContenderProvider, TxProvider > VoteItemProviders
boost::mpl::list< StakeContenderProvider > Uint256VoteItemProviders
boost::mpl::list< BlockProvider, ProofProvider, TxProvider > NullableVoteItemProviders
static bool HasAllDesirableServiceFlags(ServiceFlags services)
A shortcut for (services & GetDesirableServiceFlags(services)) == GetDesirableServiceFlags(services),...
@ MSG_AVA_STAKE_CONTENDER
ServiceFlags
nServices flags.
static const int PROTOCOL_VERSION
network protocol versioning
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
uint256 GetRandHash() noexcept
========== CONVENIENCE FUNCTIONS FOR COMMONLY USED RANDOMNESS ==========
reverse_range< T > reverse_iterate(T &x)
static uint16_t GetDefaultPort()
static std::string ToString(const CService &ip)
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
A BlockHash is a unqiue identifier for a block.
static const Currency & get()
A TxId is the identifier of a transaction.
Compare proofs by score, then by id in case of equality.
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...
TestVoteRecord(uint16_t conf)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
void UninterruptibleSleep(const std::chrono::microseconds &n)
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
@ CONFLICT
Removed for conflict with in-block transaction.
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise<void> pro...
static constexpr int AVALANCHE_MAX_INFLIGHT_POLL
How many inflight requests can exist for one item.
static constexpr uint32_t AVALANCHE_VOTE_STALE_MIN_THRESHOLD
Lowest configurable staleness threshold (finalization score + necessary votes to increase confidence ...
static constexpr int AVALANCHE_FINALIZATION_SCORE
Finalization score.