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>
41 struct AvalancheTest {
44 static std::vector<CInv> getInvsForNextPoll(
Processor &p) {
51 return p.peerManager->selectNode());
56 static uint32_t getMinQuorumScore(
const Processor &p) {
60 static double getMinQuorumConnectedScoreRatio(
const Processor &p) {
64 static void clearavaproofsNodeCounter(
Processor &p) {
71 std::make_pair(item, voteRecord));
78 static void setFinalizationTip(
Processor &p,
81 p.finalizationTip = pindex;
84 static void setLocalProofShareable(
Processor &p,
bool shareable) {
90 static void addProofToRecentfinalized(
Processor &p,
93 return p.finalizedItems.insert(proofid));
96 static bool setContenderStatusForLocalWinners(
98 std::vector<StakeContenderId> &pollableContenders) {
103 static void setStakingPreconsensus(
Processor &p,
bool enabled) {
107 static void clearInvsNotWorthPolling(
Processor &p) {
127struct AvalancheProcessorTestingSetup :
public AvalancheTestChain100Setup {
128 AvalancheProcessorTestingSetup() : AvalancheTestChain100Setup() {
129 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
false);
137 new CNode(
id++,
nullptr, addr,
144 node->m_has_all_wanted_services =
148 node->fSuccessfullyConnected =
true;
150 m_connman->AddTestNode(*
node);
159 const uint32_t height = 100;
168 BOOST_CHECK(pb.addUTXO(outpoint, amount, height,
false, key));
173 return m_node.avalanche->withPeerManager(
175 return pm.
addNode(nodeid, proofid);
179 bool addNode(
NodeId nodeid) {
180 auto proof = GetProof();
181 return m_node.avalanche->withPeerManager(
184 pm.
addNode(nodeid, proof->getId());
188 std::array<CNode *, 8> ConnectNodes() {
189 auto proof = GetProof();
192 return pm.registerProof(proof);
194 const ProofId &proofid = proof->getId();
196 std::array<CNode *, 8> nodes;
197 for (
CNode *&n : nodes) {
205 void runEventLoop() { AvalancheTest::runEventLoop(*
m_node.avalanche); }
207 NodeId getSuitableNodeToQuery() {
208 return AvalancheTest::getSuitableNodeToQuery(*
m_node.avalanche);
211 std::vector<CInv> getInvsForNextPoll() {
212 return AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
215 uint64_t getRound()
const {
216 return AvalancheTest::getRound(*
m_node.avalanche);
220 std::vector<avalanche::VoteItemUpdate> &updates,
221 std::string &error) {
228 std::vector<avalanche::VoteItemUpdate> &updates) {
236 return m_node.avalanche->addToReconcile(item);
239 void clearInvsNotWorthPolling() {
240 AvalancheTest::clearInvsNotWorthPolling(*
m_node.avalanche);
244struct BlockProvider {
245 AvalancheProcessorTestingSetup *fixture;
248 BlockProvider(AvalancheProcessorTestingSetup *_fixture)
249 : fixture(_fixture) {}
252 CBlock block = fixture->CreateAndProcessBlock({}, CScript());
256 return Assert(fixture->m_node.chainman)
257 ->m_blockman.LookupBlockIndex(blockHash);
264 std::vector<Vote> buildVotesForItems(uint32_t error,
265 std::vector<CBlockIndex *> &&items) {
266 size_t numItems = items.
size();
268 std::vector<Vote> votes;
269 votes.reserve(numItems);
274 votes.emplace_back(error, item->GetBlockHash());
282 pindex->nStatus = pindex->nStatus.withFailed();
286 return std::get<const CBlockIndex *>(item);
290struct ProofProvider {
291 AvalancheProcessorTestingSetup *fixture;
294 ProofProvider(AvalancheProcessorTestingSetup *_fixture)
295 : fixture(_fixture) {}
298 ProofRef proof = fixture->GetProof();
299 fixture->m_node.avalanche->withPeerManager(
307 return proof->
getId();
310 std::vector<Vote> buildVotesForItems(uint32_t error,
311 std::vector<ProofRef> &&items) {
312 size_t numItems = items.
size();
314 std::vector<Vote> votes;
315 votes.reserve(numItems);
319 for (
auto &item : items) {
320 votes.emplace_back(error, item->getId());
326 void invalidateItem(
const ProofRef &proof) {
327 fixture->m_node.avalanche->withPeerManager(
336 return std::get<const ProofRef>(item);
340struct StakeContenderProvider {
341 AvalancheProcessorTestingSetup *fixture;
343 std::vector<avalanche::VoteItemUpdate> updates;
346 StakeContenderProvider(AvalancheProcessorTestingSetup *_fixture)
347 : fixture(_fixture) {}
354 std::vector<CScript> winners;
355 if (!fixture->m_node.avalanche->getStakingRewardWinners(
359 const ProofRef proofWinner = fixture->GetProof();
361 fixture->m_node.avalanche->setStakingRewardWinners(chaintip,
366 const ProofRef proof = fixture->GetProof();
370 fixture->m_node.avalanche->withPeerManager(
377 fixture->m_node.avalanche->acceptStakeContender(contenderId);
379 BOOST_CHECK(fixture->m_node.avalanche->getStakeContenderStatus(
389 buildVotesForItems(uint32_t error, std::vector<StakeContenderId> &&items) {
390 size_t numItems = items.
size();
392 std::vector<Vote> votes;
393 votes.reserve(numItems);
396 std::sort(items.begin(), items.end(),
400 for (
auto &item : items) {
401 votes.emplace_back(error, item);
408 fixture->m_node.avalanche->rejectStakeContender(contenderId);
416 AvalancheTest::removeVoteRecord(*(fixture->m_node.avalanche),
421 return std::get<const StakeContenderId>(item);
426 AvalancheProcessorTestingSetup *fixture;
428 std::vector<avalanche::VoteItemUpdate> updates;
431 TxProvider(AvalancheProcessorTestingSetup *_fixture) : fixture(_fixture) {}
441 TestMemPoolEntryHelper mempoolEntryHelper;
442 auto entry = mempoolEntryHelper.Fee(1000 *
SATOSHI).FromTx(tx);
458 std::vector<Vote> buildVotesForItems(uint32_t error,
459 std::vector<CTransactionRef> &&items) {
460 size_t numItems = items.
size();
462 std::vector<Vote> votes;
463 votes.reserve(numItems);
466 std::sort(items.begin(), items.end(),
468 return lhs->GetId() < rhs->GetId();
470 for (
auto &item : items) {
471 votes.emplace_back(error, item->GetId());
487 return std::get<const CTransactionRef>(item);
493BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheProcessorTestingSetup)
497 StakeContenderProvider, TxProvider>;
499 boost::mpl::list<BlockProvider, ProofProvider, TxProvider>;
508 std::set<VoteStatus> status{
509 VoteStatus::Invalid, VoteStatus::Rejected, VoteStatus::Accepted,
510 VoteStatus::Finalized, VoteStatus::Stale,
513 auto item = provider.buildVoteItem();
515 for (
auto s : status) {
538 auto item = provider.buildVoteItem();
539 auto itemid = provider.getVoteItemId(item);
548 auto avanodes = ConnectNodes();
550 int nextNodeIndex = 0;
551 std::vector<avalanche::VoteItemUpdate> updates;
552 auto registerNewVote = [&](
const Response &resp) {
554 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
559 auto finalize = [&](
const auto finalizeItemId) {
560 Response resp = {getRound(), 0, {
Vote(0, finalizeItemId)}};
562 registerNewVote(next(resp));
563 if (updates.size() > 0) {
568 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
569 m_node.avalanche->setRecentlyFinalized(finalizeItemId);
576 auto finalizeNewItem = [&]() {
577 auto anotherItem = provider.buildVoteItem();
579 auto anotherItemId = provider.getVoteItemId(anotherItem);
582 AvalancheTest::addVoteRecord(*
m_node.avalanche, anotherVoteItem,
584 finalize(anotherItemId);
604 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
617 auto item =
decltype(provider.buildVoteItem())();
624 item = provider.buildVoteItem();
635 auto itemZero =
decltype(provider.buildVoteItem())();
648 auto item = provider.buildVoteItem();
658 const uint32_t invType = provider.invType;
660 auto item = provider.buildVoteItem();
661 auto itemid = provider.getVoteItemId(item);
664 auto avanodes = ConnectNodes();
672 auto invs = getInvsForNextPoll();
680 int nextNodeIndex = 0;
681 std::vector<avalanche::VoteItemUpdate> updates;
682 auto registerNewVote = [&](
const Response &resp) {
684 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
690 for (
int i = 0; i < 6; i++) {
691 registerNewVote(next(resp));
698 resp = {getRound(), 0, {
Vote(-1, itemid)}};
699 registerNewVote(next(resp));
704 resp = {getRound(), 0, {
Vote(0, itemid)}};
705 for (
int i = 1; i < 7; i++) {
706 registerNewVote(next(resp));
713 resp = {getRound(), 0, {
Vote(-1, itemid)}};
714 registerNewVote(next(resp));
718 registerNewVote(next(resp));
723 resp = {getRound(), 0, {
Vote(0, itemid)}};
724 for (
int i = 2; i < 8; i++) {
725 registerNewVote(next(resp));
733 registerNewVote(next(resp));
740 invs = getInvsForNextPoll();
746 registerNewVote(next(resp));
748 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
749 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
752 invs = getInvsForNextPoll();
756 item = provider.buildVoteItem();
757 itemid = provider.getVoteItemId(item);
761 invs = getInvsForNextPoll();
766 resp = {getRound(), 0, {
Vote(1, itemid)}};
767 for (
int i = 0; i < 6; i++) {
768 registerNewVote(next(resp));
774 registerNewVote(next(resp));
777 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
778 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
782 registerNewVote(next(resp));
788 invs = getInvsForNextPoll();
794 registerNewVote(next(resp));
797 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
798 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
801 invs = getInvsForNextPoll();
807 const uint32_t invType = provider.invType;
809 auto itemA = provider.buildVoteItem();
810 auto itemidA = provider.getVoteItemId(itemA);
812 auto itemB = provider.buildVoteItem();
813 auto itemidB = provider.getVoteItemId(itemB);
816 auto avanodes = ConnectNodes();
824 auto invs = getInvsForNextPoll();
829 uint64_t round = getRound();
831 std::vector<avalanche::VoteItemUpdate> updates;
833 {round, 0, {
Vote(0, itemidA)}}, updates));
837 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
840 invs = getInvsForNextPoll();
844 for (
size_t i = 0; i < invs.size(); i++) {
850 for (
int i = 0; i < 4; i++) {
851 NodeId nodeid = getSuitableNodeToQuery();
853 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
859 NodeId nodeid = getSuitableNodeToQuery();
861 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
867 NodeId firstNodeid = getSuitableNodeToQuery();
869 NodeId secondNodeid = getSuitableNodeToQuery();
875 BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates));
877 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemA);
878 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
881 invs = getInvsForNextPoll();
887 BOOST_CHECK(registerVotes(secondNodeid, resp, updates));
889 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemB);
890 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
893 invs = getInvsForNextPoll();
899 const uint32_t invType = provider.invType;
901 auto item = provider.buildVoteItem();
902 auto itemid = provider.getVoteItemId(item);
909 std::set<NodeId> avanodeIds;
910 auto avanodes = ConnectNodes();
911 for (
auto avanode : avanodes) {
913 avanodeIds.insert(avanode->GetId());
916 auto getSelectedAvanodeId = [&]() {
917 NodeId avanodeid = getSuitableNodeToQuery();
918 BOOST_CHECK(avanodeIds.find(avanodeid) != avanodeIds.end());
923 NodeId avanodeid = getSelectedAvanodeId();
927 auto invs = getInvsForNextPoll();
932 std::set<NodeId> unselectedNodeids = avanodeIds;
933 unselectedNodeids.erase(avanodeid);
934 const size_t remainingNodeIds = unselectedNodeids.size();
936 uint64_t round = getRound();
937 for (
size_t i = 0; i < remainingNodeIds; i++) {
942 NodeId nodeid = getSuitableNodeToQuery();
943 BOOST_CHECK(unselectedNodeids.find(nodeid) != avanodeIds.end());
944 unselectedNodeids.erase(nodeid);
954 std::vector<avalanche::VoteItemUpdate> updates;
955 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
962 auto checkRegisterVotesError = [&](
NodeId nodeid,
964 const std::string &expectedError) {
972 checkRegisterVotesError(avanodeid, next(resp),
"unexpected-ava-response");
981 resp = {round, 0, {
Vote(0, itemid),
Vote(0, itemid)}};
983 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
987 resp = {getRound(), 0, {}};
989 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
993 resp = {getRound(), 0, {
Vote()}};
995 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1002 invs = getInvsForNextPoll();
1005 item = provider.buildVoteItem();
1006 itemid = provider.getVoteItemId(item);
1009 invs = getInvsForNextPoll();
1013 uint64_t queryRound = getRound();
1016 resp = {queryRound + 1, 0, {
Vote()}};
1017 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1019 resp = {queryRound - 1, 0, {
Vote()}};
1020 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1024 resp = {queryRound, 0, {
Vote(0, itemid)}};
1025 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1028 resp = {queryRound, 0, {
Vote(0, itemid)}};
1029 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1034 const auto item2 = provider.buildVoteItem();
1037 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1038 resp = {getRound(), 0, {votes[1], votes[0]}};
1040 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1044 resp = {getRound(), 0, votes};
1046 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1053 const uint32_t invType = provider.invType;
1055 auto itemA = provider.buildVoteItem();
1056 auto itemB = provider.buildVoteItem();
1058 auto avanodes = ConnectNodes();
1059 int nextNodeIndex = 0;
1062 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1068 auto invs = getInvsForNextPoll();
1070 for (
size_t i = 0; i < invs.size(); i++) {
1076 provider.invalidateItem(itemB);
1078 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1079 std::vector<avalanche::VoteItemUpdate> updates;
1082 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1083 goodResp, updates));
1087 invs = getInvsForNextPoll();
1090 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1093 Response badResp{getRound(), 0, votes};
1097 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1098 badResp, updates, error));
1102 votes = provider.buildVotesForItems(1, {itemA});
1103 auto registerNewVote = [&]() {
1104 Response resp = {getRound(), 0, votes};
1106 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1107 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1109 for (
size_t i = 0; i < 4000; i++) {
1111 if (updates.size() > 0 &&
1112 updates[0].getStatus() == VoteStatus::Invalid) {
1118 invs = getInvsForNextPoll();
1122 badResp =
Response(getRound(), 0, votes);
1125 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1126 badResp, updates, error));
1130BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1135 auto queryTimeDuration = std::chrono::milliseconds(10);
1136 setArg(
"-avatimeout",
ToString(queryTimeDuration.count()));
1138 setArg(
"-avalanchestakingpreconsensus",
"0");
1141 m_node.avalanche = Processor::MakeProcessor(
1145 const auto item = provider.buildVoteItem();
1146 const auto itemid = provider.getVoteItemId(item);
1156 for (
int i = 0; i < 10; i++) {
1158 avanodeid = getSuitableNodeToQuery();
1160 auto start = Now<SteadyMilliseconds>();
1164 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1167 std::vector<avalanche::VoteItemUpdate> updates;
1168 bool ret = registerVotes(avanodeid, next(resp), updates);
1169 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1180 avanodeid = getSuitableNodeToQuery();
1184 std::this_thread::sleep_for(queryTimeDuration);
1186 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1192 const uint32_t invType = provider.invType;
1195 auto proof = GetProof();
1199 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1200 for (
auto &n : nodes) {
1206 const auto item = provider.buildVoteItem();
1207 const auto itemid = provider.getVoteItemId(item);
1211 std::map<NodeId, uint64_t> node_round_map;
1213 NodeId nodeid = getSuitableNodeToQuery();
1214 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1215 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1216 auto invs = getInvsForNextPoll();
1224 auto suitablenodeid = getSuitableNodeToQuery();
1226 auto invs = getInvsForNextPoll();
1232 auto it = node_round_map.begin();
1234 std::vector<avalanche::VoteItemUpdate> updates;
1235 BOOST_CHECK(registerVotes(it->first, resp, updates));
1236 node_round_map.erase(it);
1238 invs = getInvsForNextPoll();
1245 std::vector<VoteItemUpdate> updates;
1247 CBlock block = CreateAndProcessBlock({}, CScript());
1253 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1257 auto avanodes = ConnectNodes();
1266 uint64_t round = getRound();
1270 for (
size_t i = 0; i < avanodes.size(); i++) {
1272 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1276 const NodeId firstNodeId = getSuitableNodeToQuery();
1277 std::map<NodeId, uint64_t> node_round_map;
1279 for (
size_t i = 0; i < avanodes.size(); i++) {
1280 NodeId nodeid = getSuitableNodeToQuery();
1281 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1282 node_round_map[nodeid] = getRound();
1288 auto confidence =
m_node.avalanche->getConfidence(pindex);
1289 BOOST_REQUIRE(confidence > 0);
1291 for (
auto &[nodeid, r] : node_round_map) {
1292 if (nodeid == firstNodeId) {
1299 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1304 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1311 CBlock block = CreateAndProcessBlock({}, CScript());
1317 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1324 std::chrono::steady_clock::time_point start,
stop;
1334 auto avanodes = ConnectNodes();
1337 NodeId nodeid = getSuitableNodeToQuery();
1338 BOOST_CHECK_NE(nodeid,
NO_NODE);
1341 uint64_t queryRound = getRound();
1345 for (
int i = 0; i < 60 * 1000; i++) {
1349 if (getRound() == queryRound + avanodes.size()) {
1358 uint64_t responseRound = getRound();
1359 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1361 std::vector<VoteItemUpdate> updates;
1363 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1366 for (
int i = 0; i < 10000; i++) {
1369 if (getRound() != responseRound) {
1370 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1389 schedulerThread.join();
1394 std::chrono::steady_clock::time_point start,
stop;
1396 std::thread schedulerThread;
1406 m_node.avalanche.reset();
1413 schedulerThread.join();
1420 auto addProofToReconcile = [&](uint32_t proofScore) {
1430 auto proof = addProofToReconcile(++score);
1432 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1441 for (
size_t i = 0; i < 10; i++) {
1442 auto proof = addProofToReconcile(++score);
1444 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1449 lastProofId = proof->
getId();
1452 for (
size_t i = 0; i < 10; i++) {
1453 auto proof = addProofToReconcile(--score);
1455 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1463 auto proof = addProofToReconcile(--score);
1464 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1465 for (
auto &inv : invs) {
1466 BOOST_CHECK_NE(inv.hash, proof->
getId());
1472 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1473 setArg(
"-avalancheconflictingproofcooldown",
"0");
1487 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1488 coins.
AddCoin(conflictingOutpoint,
1491 coins.
AddCoin(immatureOutpoint,
1496 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1497 uint32_t height = 10) {
1504 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1505 auto validProof = buildProof(conflictingOutpoint, 2);
1506 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1557 int minStake = 400'000'000;
1558 setArg(
"-avaminquorumstake",
ToString(minStake));
1559 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1563 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1571 setArg(
"-avaproof", localProof->ToHex());
1575 m_node.avalanche = Processor::MakeProcessor(
1582 localProof->getId());
1586 AvalancheTest::getMinQuorumConnectedScoreRatio(*
m_node.avalanche), 0.5);
1608 for (
NodeId id = 0;
id < 8;
id++) {
1626 const int64_t tipTime =
1630 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1631 const int height = 100;
1632 const bool isCoinbase =
false;
1639 height, isCoinbase),
1644 auto proof2 = pb.
build();
1655 pm.
addNode(8, proof2->getId());
1674 m_node.avalanche->withPeerManager(
1685 auto spendProofUtxo = [&](
ProofRef proof) {
1698 for (int64_t i = 0; i < 6; i++) {
1700 CreateAndProcessBlock({}, CScript());
1704 ->GetMedianTimePast(),
1705 proof2->getExpirationTime());
1716 spendProofUtxo(proof1);
1723 spendProofUtxo(
m_node.avalanche->getLocalProof());
1735 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1738 {
"",
"",
"",
false},
1739 {
"-1",
"-1",
"-1",
false},
1742 {
"-1",
"0",
"0",
false},
1743 {
"-0.01",
"0",
"0",
false},
1744 {
"21000000000000.01",
"0",
"0",
false},
1747 {
"0",
"-1",
"0",
false},
1748 {
"0",
"1.1",
"0",
false},
1751 {
"0",
"0",
"-1",
false},
1754 {
"0",
"0",
"0",
true},
1755 {
"0.00",
"0",
"0",
true},
1756 {
"0.01",
"0",
"0",
true},
1757 {
"1",
"0.1",
"0",
true},
1758 {
"10",
"0.5",
"0",
true},
1759 {
"10",
"1",
"0",
true},
1760 {
"21000000000000.00",
"0",
"0",
true},
1761 {
"0",
"0",
"1",
true},
1762 {
"0",
"0",
"100",
true},
1767 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1769 setArg(
"-avaminquorumstake", stake);
1770 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1771 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1774 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1794 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1795 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1798 auto processor = Processor::MakeProcessor(
1802 auto addNode = [&](
NodeId nodeid) {
1815 for (
NodeId id = 100;
id < 108;
id++) {
1820 minAvaproofsMessages <= 0);
1822 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1825 processor->avaproofsSent(i);
1829 processor->avaproofsSent(i);
1835 addNode(minAvaproofsMessages);
1836 processor->avaproofsSent(minAvaproofsMessages);
1840 AvalancheTest::clearavaproofsNodeCounter(*processor);
1844 checkMinAvaproofsMessages(0);
1845 checkMinAvaproofsMessages(1);
1846 checkMinAvaproofsMessages(10);
1847 checkMinAvaproofsMessages(100);
1852 setArg(
"-avastalevotethreshold",
1854 setArg(
"-avastalevotefactor",
"2");
1856 setArg(
"-avalanchestakingpreconsensus",
"0");
1858 const std::vector<std::tuple<int, int>> testCases = {
1865 m_node.avalanche = Processor::MakeProcessor(
1874 const uint32_t invType = provider.invType;
1876 const auto item = provider.buildVoteItem();
1877 const auto itemid = provider.getVoteItemId(item);
1880 auto avanodes = ConnectNodes();
1881 int nextNodeIndex = 0;
1883 std::vector<avalanche::VoteItemUpdate> updates;
1884 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
1887 auto invs = getInvsForNextPoll();
1894 auto registerNewVote = [&](
const Response &resp) {
1896 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1897 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1901 for (
int i = 0; i < numYesVotes; i++) {
1903 registerNewVote(next(resp));
1906 i >= 6 ? i - 5 : 0);
1911 for (
int i = 0; i < numNeutralVotes; i++) {
1913 registerNewVote(next(resp));
1918 invs = getInvsForNextPoll();
1925 registerNewVote(next(resp));
1927 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
1928 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
1931 invs = getInvsForNextPoll();
1937 BlockProvider provider(
this);
1941 std::vector<CBlockIndex *> blockIndexes;
1945 blockIndexes.push_back(pindex);
1948 auto invs = getInvsForNextPoll();
1960 std::vector<Vote> votes;
1963 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
1964 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
1967 auto avanodes = ConnectNodes();
1968 int nextNodeIndex = 0;
1970 std::vector<avalanche::VoteItemUpdate> updates;
1971 auto registerNewVote = [&]() {
1972 Response resp = {getRound(), 0, votes};
1974 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1975 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1981 bool eleventhBlockFinalized =
false;
1982 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
1985 for (
auto &update : updates) {
1986 if (update.getStatus() == VoteStatus::Finalized &&
1987 provider.fromAnyVoteItem(update.getVoteItem())
1988 ->GetBlockHash() == eleventhBlockHash) {
1989 eleventhBlockFinalized =
true;
2000 clearInvsNotWorthPolling();
2001 invs = getInvsForNextPoll();
2003 for (
size_t i = 0; i < 10; i++) {
2017 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2019 activeChainstate.InvalidateBlock(state, tip);
2022 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2025 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2033 activeChainstate.ResetBlockFailureFlags(tip);
2035 activeChainstate.ActivateBestChain(state);
2039 clearInvsNotWorthPolling();
2040 invs = getInvsForNextPoll();
2047 for (
auto &inv : invs) {
2048 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2051 bool tipFinalized =
false;
2052 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2055 for (
auto &update : updates) {
2056 if (update.getStatus() == VoteStatus::Finalized &&
2057 provider.fromAnyVoteItem(update.getVoteItem())
2058 ->GetBlockHash() == tiphash) {
2059 tipFinalized =
true;
2068 clearInvsNotWorthPolling();
2069 invs = getInvsForNextPoll();
2077 BlockHash alttiphash = alttip->GetBlockHash();
2078 votes = {{1, alttiphash}};
2080 bool alttipInvalidated =
false;
2081 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2084 for (
auto &update : updates) {
2085 if (update.getStatus() == VoteStatus::Invalid &&
2086 provider.fromAnyVoteItem(update.getVoteItem())
2087 ->GetBlockHash() == alttiphash) {
2088 alttipInvalidated =
true;
2093 invs = getInvsForNextPoll();
2104 const int numberElementsEachType = 100;
2107 std::vector<ProofRef> proofs;
2108 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2112 proofs.emplace_back(std::move(proof));
2114 Shuffle(proofs.begin(), proofs.end(), rng);
2116 std::vector<CBlockIndex> indexes;
2117 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2120 indexes.emplace_back(std::move(index));
2122 Shuffle(indexes.begin(), indexes.end(), rng);
2124 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2125 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2131 for (
size_t i = 0; i < numberElementsEachType; i++) {
2133 const size_t firstType = rng.
randrange(numTypes);
2135 for (
size_t j = 0; j < numTypes; j++) {
2136 switch ((firstType + j) % numTypes) {
2139 writeView->insert(std::make_pair(
2140 std::get<0>(allItems)[i],
VoteRecord(
true)));
2144 writeView->insert(std::make_pair(
2145 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2156 auto readView = voteMap.getReadView();
2157 auto it = readView.begin();
2160 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2161 for (
size_t i = 0; i < numberElementsEachType; i++) {
2162 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2164 uint32_t currentScore =
2165 std::get<const ProofRef>(it->first)->getScore();
2166 BOOST_CHECK_LT(currentScore, lastScore);
2167 lastScore = currentScore;
2175 for (
size_t i = 0; i < numberElementsEachType; i++) {
2176 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2179 std::get<const CBlockIndex *>(it->first)->nChainWork;
2181 lastWork = currentWork;
2194 const auto block = std::make_shared<const CBlock>(
2195 this->CreateBlock({}, CScript(), chainstate));
2222 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
2235 auto now = GetTime<std::chrono::seconds>();
2241 std::vector<CScript> winners;
2244 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2249 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2254 prevBlock.
nTime = now.count();
2259 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2262 size_t numProofs = 10;
2263 std::vector<ProofRef> proofs;
2264 proofs.reserve(numProofs);
2265 for (
size_t i = 0; i < numProofs; i++) {
2269 auto proof = GetProof(payoutScript);
2275 return pm.setFinalized(peer.peerid);
2279 proofs.emplace_back(std::move(proof));
2287 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2290 auto winnerExists = [&](
const CScript &expectedWinner) {
2291 const std::string winnerString =
FormatScript(expectedWinner);
2293 for (
const ProofRef &proof : proofs) {
2304 prevBlock.
nTime = now.count();
2309 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2315 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2321 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2325 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2330 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2334 m_node.avalanche->cleanupStakingRewards(101);
2338 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2342 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2348 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2352 m_node.avalanche->cleanupStakingRewards(200);
2356 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2358 !
m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2370 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2376 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2384 auto localProof = buildProof(outpoint, 1, 100);
2387 setArg(
"-avaproof", localProof->ToHex());
2388 setArg(
"-avalancheconflictingproofcooldown",
"0");
2389 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2390 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2394 m_node.avalanche = Processor::MakeProcessor(
2399 localProof->getId());
2401 auto checkLocalProofState = [&](
const bool boundToPeer,
2406 return pm.isBoundToPeer(localProof->getId());
2409 BOOST_CHECK_MESSAGE(
2410 m_node.avalanche->getLocalProofRegistrationState().GetResult() ==
2412 m_node.avalanche->getLocalProofRegistrationState().ToString());
2419 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2423 AvalancheTest::setLocalProofShareable(*
m_node.avalanche,
true);
2425 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2426 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2430 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2431 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2435 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2439 auto conflictingProof = buildProof(outpoint, 2, 100);
2445 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2446 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2450 setArg(
"-avalancheconflictingproofcooldown",
"0");
2451 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2471 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2478 auto proof = buildProof(outpoint, 1);
2497 AvalancheTest::addProofToRecentfinalized(*
m_node.avalanche, proof->
getId());
2504 return peer.hasFinalized;
2511 auto betterProof = buildProof(outpoint, 2);
2534 m_node.avalanche = Processor::MakeProcessor(
2540 auto now = GetTime<std::chrono::seconds>();
2543 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
true);
2551 const ProofId proofid1 = proof1->getId();
2556 const ProofId proofid2 = proof2->getId();
2567 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2569 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2575 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2580 for (
NodeId n = 0; n < 8; n++) {
2585 return pm.setFinalized(peer.peerid);
2594 CBlock block = CreateAndProcessBlock({}, CScript());
2597 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2598 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2604 std::vector<CScript> winners;
2608 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2613 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2617 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2619 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2625 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2631 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2639 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2642 m_node.avalanche->getStakeContenderStatus(contender1_block1), -1);
2644 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2647 m_node.avalanche->getStakeContenderStatus(contender2_block1), -1);
2649 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2652 m_node.avalanche->setStakingRewardWinners(
2653 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2658 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2661 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2664 m_node.avalanche->withPeerManager(
2670 const ProofId proofid3 = proof3->getId();
2673 for (
NodeId n = 0; n < 8; n++) {
2679 block = CreateAndProcessBlock({}, CScript());
2682 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2683 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2687 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2691 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2693 m_node.avalanche->getStakeContenderStatus(contender2_block2), -1);
2700 m_node.avalanche->getStakeContenderStatus(contender1_block3), -1);
2704 m_node.avalanche->getStakeContenderStatus(contender2_block3), -1);
2707 m_node.avalanche->withPeerManager(
2711 size_t numProofs = 8;
2712 std::vector<ProofRef> proofs;
2713 proofs.reserve(numProofs);
2714 for (
size_t i = 0; i < numProofs; i++) {
2723 return pm.setFinalized(peer.peerid);
2726 proofs.emplace_back(std::move(proof));
2731 const ProofId proofid = proofs[0]->getId();
2732 for (
NodeId n = 0; n < 8; n++) {
2742 std::vector<CScript> winners;
2743 for (
int attempt = 0; attempt < 10; attempt++) {
2745 block = CreateAndProcessBlock({}, CScript());
2748 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2749 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2755 chaintip->GetBlockHash(), winners));
2756 if (winners.size() == 8) {
2764 size_t numAccepted = 0;
2765 for (
const auto &proof : proofs) {
2769 if (
m_node.avalanche->getStakeContenderStatus(contender) == 0) {
2771 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2779 block = CreateAndProcessBlock({}, CScript());
2782 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2787 m_node.avalanche->withPeerManager(
2789 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2798 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2799 bestproof->getPayoutScript()) == winners.end());
2806 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2817 block = CreateAndProcessBlock({}, CScript());
2820 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2821 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2822 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
2829 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2843 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2844 bestproof->getPayoutScript()) == winners.end());
2852 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2863 auto now = GetTime<std::chrono::seconds>();
2867 auto localWinnerProof =
2869 ProofId localWinnerProofId = localWinnerProof->getId();
2871 localWinnerProof->getId());
2880 for (
NodeId n = 0; n < 8; n++) {
2881 pm.
addNode(n, localWinnerProofId);
2884 return pm.setFinalized(peer.peerid);
2891 chaintip->
nTime = now.count();
2897 std::vector<ProofRef> acceptedContenderProofs;
2898 acceptedContenderProofs.push_back(localWinnerProof);
2905 for (
size_t numContenders = 2;
2909 m_node.avalanche->withPeerManager(
2915 if (rank <= bestRank) {
2917 acceptedContenderProofs.push_back(proof);
2918 const size_t numAccepted =
2920 acceptedContenderProofs.size());
2921 std::sort(acceptedContenderProofs.begin(),
2922 acceptedContenderProofs.begin() + numAccepted,
2924 const ProofId leftProofId = left->getId();
2925 const ProofId rightProofId = right->getId();
2926 const StakeContenderId leftContenderId(chaintipHash,
2928 const StakeContenderId rightContenderId(chaintipHash,
2930 return RewardRankComparator()(
2932 leftContenderId.ComputeProofRewardRank(
2933 MIN_VALID_PROOF_SCORE),
2934 leftProofId, rightContenderId,
2935 rightContenderId.ComputeProofRewardRank(
2936 MIN_VALID_PROOF_SCORE),
2941 std::vector<StakeContenderId> pollableContenders;
2942 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
2943 *
m_node.avalanche, chaintip, pollableContenders));
2945 pollableContenders.size(),
2950 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
2954 chaintipHash, acceptedContenderProofs[i]->getId());
2956 std::find(pollableContenders.begin(), pollableContenders.end(),
2957 acceptedContenderId) != pollableContenders.end());
2959 m_node.avalanche->getStakeContenderStatus(acceptedContenderId),
2964 std::set<StakeContenderId> unacceptedContenderIds(
2965 pollableContenders.begin(), pollableContenders.end());
2966 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
2968 chaintipHash, acceptedContenderProof->getId());
2969 unacceptedContenderIds.erase(acceptedContenderId);
2972 for (
auto cid : unacceptedContenderIds) {
2979 m_node.avalanche->getStakeContenderStatus(localWinnerContenderId),
2984BOOST_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
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()
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.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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.