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/mpl/size.hpp>
31#include <boost/test/unit_test.hpp>
43 struct AvalancheTest {
46 static std::vector<CInv> getInvsForNextPoll(
Processor &p) {
54 return p.peerManager->selectNode());
59 static uint32_t getMinQuorumScore(
const Processor &p) {
63 static double getMinQuorumConnectedScoreRatio(
const Processor &p) {
67 static void clearavaproofsNodeCounter(
Processor &p) {
74 std::make_pair(item, voteRecord));
81 static void setFinalizationTip(
Processor &p,
84 p.finalizationTip = pindex;
87 static void setLocalProofShareable(
Processor &p,
bool shareable) {
93 static void addProofToRecentfinalized(
Processor &p,
96 return p.finalizedItems.insert(proofid));
99 static bool setContenderStatusForLocalWinners(
101 std::vector<StakeContenderId> &pollableContenders) {
106 static void setStakingPreconsensus(
Processor &p,
bool enabled) {
110 static void clearInvsNotWorthPolling(
Processor &p) {
130struct AvalancheProcessorTestingSetup :
public AvalancheTestChain100Setup {
131 AvalancheProcessorTestingSetup() : AvalancheTestChain100Setup() {
132 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
false);
140 new CNode(
id++,
nullptr, addr,
147 node->m_has_all_wanted_services =
151 node->fSuccessfullyConnected =
true;
153 m_connman->AddTestNode(*
node);
162 const uint32_t height = 100;
171 BOOST_CHECK(pb.addUTXO(outpoint, amount, height,
false, key));
176 return m_node.avalanche->withPeerManager(
178 return pm.
addNode(nodeid, proofid,
183 bool addNode(
NodeId nodeid) {
184 auto proof = GetProof();
185 return m_node.avalanche->withPeerManager(
188 pm.
addNode(nodeid, proof->getId(),
193 std::array<CNode *, 8> ConnectNodes() {
194 auto proof = GetProof();
197 return pm.registerProof(proof);
199 const ProofId &proofid = proof->getId();
201 std::array<CNode *, 8> nodes;
202 for (
CNode *&n : nodes) {
210 void runEventLoop() { AvalancheTest::runEventLoop(*
m_node.avalanche); }
212 NodeId getSuitableNodeToQuery() {
213 return AvalancheTest::getSuitableNodeToQuery(*
m_node.avalanche);
216 std::vector<CInv> getInvsForNextPoll() {
217 return AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
220 uint64_t getRound()
const {
221 return AvalancheTest::getRound(*
m_node.avalanche);
225 std::vector<avalanche::VoteItemUpdate> &updates,
226 std::string &error) {
233 std::vector<avalanche::VoteItemUpdate> &updates) {
241 return m_node.avalanche->addToReconcile(item);
244 void clearInvsNotWorthPolling() {
245 AvalancheTest::clearInvsNotWorthPolling(*
m_node.avalanche);
249struct BlockProvider {
250 AvalancheProcessorTestingSetup *fixture;
253 BlockProvider(AvalancheProcessorTestingSetup *_fixture)
254 : fixture(_fixture) {}
257 CBlock block = fixture->CreateAndProcessBlock({}, CScript());
261 return Assert(fixture->m_node.chainman)
262 ->m_blockman.LookupBlockIndex(blockHash);
269 std::vector<Vote> buildVotesForItems(uint32_t error,
270 std::vector<CBlockIndex *> &&items) {
271 size_t numItems = items.
size();
273 std::vector<Vote> votes;
274 votes.reserve(numItems);
279 votes.emplace_back(error, item->GetBlockHash());
287 pindex->nStatus = pindex->nStatus.withFailed();
291 return std::get<const CBlockIndex *>(item);
295struct ProofProvider {
296 AvalancheProcessorTestingSetup *fixture;
299 ProofProvider(AvalancheProcessorTestingSetup *_fixture)
300 : fixture(_fixture) {}
303 ProofRef proof = fixture->GetProof();
304 fixture->m_node.avalanche->withPeerManager(
312 return proof->
getId();
315 std::vector<Vote> buildVotesForItems(uint32_t error,
316 std::vector<ProofRef> &&items) {
317 size_t numItems = items.
size();
319 std::vector<Vote> votes;
320 votes.reserve(numItems);
324 for (
auto &item : items) {
325 votes.emplace_back(error, item->getId());
331 void invalidateItem(
const ProofRef &proof) {
332 fixture->m_node.avalanche->withPeerManager(
341 return std::get<const ProofRef>(item);
345struct StakeContenderProvider {
346 AvalancheProcessorTestingSetup *fixture;
348 std::vector<avalanche::VoteItemUpdate> updates;
351 StakeContenderProvider(AvalancheProcessorTestingSetup *_fixture)
352 : fixture(_fixture) {}
359 std::vector<CScript> winners;
360 if (!fixture->m_node.avalanche->getStakingRewardWinners(
364 const ProofRef proofWinner = fixture->GetProof();
366 fixture->m_node.avalanche->setStakingRewardWinners(chaintip,
371 const ProofRef proof = fixture->GetProof();
375 fixture->m_node.avalanche->withPeerManager(
382 fixture->m_node.avalanche->acceptStakeContender(contenderId);
384 BOOST_CHECK(fixture->m_node.avalanche->getStakeContenderStatus(
394 buildVotesForItems(uint32_t error, std::vector<StakeContenderId> &&items) {
395 size_t numItems = items.
size();
397 std::vector<Vote> votes;
398 votes.reserve(numItems);
401 std::sort(items.begin(), items.end(),
405 for (
auto &item : items) {
406 votes.emplace_back(error, item);
413 fixture->m_node.avalanche->rejectStakeContender(contenderId);
421 AvalancheTest::removeVoteRecord(*(fixture->m_node.avalanche),
426 return std::get<const StakeContenderId>(item);
431 AvalancheProcessorTestingSetup *fixture;
433 std::vector<avalanche::VoteItemUpdate> updates;
436 TxProvider(AvalancheProcessorTestingSetup *_fixture) : fixture(_fixture) {}
446 TestMemPoolEntryHelper mempoolEntryHelper;
447 auto entry = mempoolEntryHelper.Fee(1000 *
SATOSHI).FromTx(tx);
463 std::vector<Vote> buildVotesForItems(uint32_t error,
464 std::vector<CTransactionRef> &&items) {
465 size_t numItems = items.
size();
467 std::vector<Vote> votes;
468 votes.reserve(numItems);
471 std::sort(items.begin(), items.end(),
473 return lhs->GetId() < rhs->GetId();
475 for (
auto &item : items) {
476 votes.emplace_back(error, item->GetId());
492 return std::get<const CTransactionRef>(item);
498BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheProcessorTestingSetup)
502 StakeContenderProvider, TxProvider>;
504 boost::mpl::list<BlockProvider, ProofProvider, TxProvider>;
513 std::set<VoteStatus> status{
514 VoteStatus::Invalid, VoteStatus::Rejected, VoteStatus::Accepted,
515 VoteStatus::Finalized, VoteStatus::Stale,
518 auto item = provider.buildVoteItem();
520 for (
auto s : status) {
543 auto item = provider.buildVoteItem();
544 auto itemid = provider.getVoteItemId(item);
553 auto avanodes = ConnectNodes();
555 int nextNodeIndex = 0;
556 std::vector<avalanche::VoteItemUpdate> updates;
557 auto registerNewVote = [&](
const Response &resp) {
559 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
561 bool vote_is_registered = registerVotes(nodeid, resp, updates, error);
562 BOOST_CHECK_MESSAGE(vote_is_registered,
563 "registerVotes failed with error: " << error);
567 auto finalize = [&](
const auto finalizeItemId) {
568 Response resp = {getRound(), 0, {
Vote(0, finalizeItemId)}};
570 registerNewVote(next(resp));
571 if (updates.size() > 0) {
576 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
577 m_node.avalanche->setRecentlyFinalized(finalizeItemId);
584 auto finalizeNewItem = [&]() {
585 auto anotherItem = provider.buildVoteItem();
587 auto anotherItemId = provider.getVoteItemId(anotherItem);
590 AvalancheTest::addVoteRecord(*
m_node.avalanche, anotherVoteItem,
592 finalize(anotherItemId);
612 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
625 auto item =
decltype(provider.buildVoteItem())();
632 item = provider.buildVoteItem();
643 auto itemZero =
decltype(provider.buildVoteItem())();
656 auto item = provider.buildVoteItem();
666 const uint32_t invType = provider.invType;
668 auto item = provider.buildVoteItem();
669 auto itemid = provider.getVoteItemId(item);
672 auto avanodes = ConnectNodes();
680 auto invs = getInvsForNextPoll();
688 int nextNodeIndex = 0;
689 std::vector<avalanche::VoteItemUpdate> updates;
690 auto registerNewVote = [&](
const Response &resp) {
692 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
698 for (
int i = 0; i < 6; i++) {
699 registerNewVote(next(resp));
706 resp = {getRound(), 0, {
Vote(-1, itemid)}};
707 registerNewVote(next(resp));
712 resp = {getRound(), 0, {
Vote(0, itemid)}};
713 for (
int i = 1; i < 7; i++) {
714 registerNewVote(next(resp));
721 resp = {getRound(), 0, {
Vote(-1, itemid)}};
722 registerNewVote(next(resp));
726 registerNewVote(next(resp));
731 resp = {getRound(), 0, {
Vote(0, itemid)}};
732 for (
int i = 2; i < 8; i++) {
733 registerNewVote(next(resp));
741 registerNewVote(next(resp));
748 invs = getInvsForNextPoll();
754 registerNewVote(next(resp));
756 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
757 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
760 invs = getInvsForNextPoll();
764 item = provider.buildVoteItem();
765 itemid = provider.getVoteItemId(item);
769 invs = getInvsForNextPoll();
774 resp = {getRound(), 0, {
Vote(1, itemid)}};
775 for (
int i = 0; i < 6; i++) {
776 registerNewVote(next(resp));
782 registerNewVote(next(resp));
785 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
786 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
790 registerNewVote(next(resp));
796 invs = getInvsForNextPoll();
802 registerNewVote(next(resp));
805 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
806 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
809 invs = getInvsForNextPoll();
815 const uint32_t invType = provider.invType;
817 auto itemA = provider.buildVoteItem();
818 auto itemidA = provider.getVoteItemId(itemA);
820 auto itemB = provider.buildVoteItem();
821 auto itemidB = provider.getVoteItemId(itemB);
824 auto avanodes = ConnectNodes();
832 auto invs = getInvsForNextPoll();
837 uint64_t round = getRound();
839 std::vector<avalanche::VoteItemUpdate> updates;
841 {round, 0, {
Vote(0, itemidA)}}, updates));
845 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
848 invs = getInvsForNextPoll();
852 for (
size_t i = 0; i < invs.size(); i++) {
858 for (
int i = 0; i < 4; i++) {
859 NodeId nodeid = getSuitableNodeToQuery();
861 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
867 NodeId nodeid = getSuitableNodeToQuery();
869 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
875 NodeId firstNodeid = getSuitableNodeToQuery();
877 NodeId secondNodeid = getSuitableNodeToQuery();
883 BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates));
885 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemA);
886 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
889 invs = getInvsForNextPoll();
895 BOOST_CHECK(registerVotes(secondNodeid, resp, updates));
897 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemB);
898 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
901 invs = getInvsForNextPoll();
907 const uint32_t invType = provider.invType;
909 auto item = provider.buildVoteItem();
910 auto itemid = provider.getVoteItemId(item);
917 std::set<NodeId> avanodeIds;
918 auto avanodes = ConnectNodes();
919 for (
auto avanode : avanodes) {
921 avanodeIds.insert(avanode->GetId());
924 auto getSelectedAvanodeId = [&]() {
925 NodeId avanodeid = getSuitableNodeToQuery();
926 BOOST_CHECK(avanodeIds.find(avanodeid) != avanodeIds.end());
931 NodeId avanodeid = getSelectedAvanodeId();
935 auto invs = getInvsForNextPoll();
940 std::set<NodeId> unselectedNodeids = avanodeIds;
941 unselectedNodeids.erase(avanodeid);
942 const size_t remainingNodeIds = unselectedNodeids.size();
944 uint64_t round = getRound();
945 for (
size_t i = 0; i < remainingNodeIds; i++) {
950 NodeId nodeid = getSuitableNodeToQuery();
951 BOOST_CHECK(unselectedNodeids.find(nodeid) != avanodeIds.end());
952 unselectedNodeids.erase(nodeid);
962 std::vector<avalanche::VoteItemUpdate> updates;
963 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
970 auto checkRegisterVotesError = [&](
NodeId nodeid,
972 const std::string &expectedError) {
980 checkRegisterVotesError(avanodeid, next(resp),
"unexpected-ava-response");
989 resp = {round, 0, {
Vote(0, itemid),
Vote(0, itemid)}};
991 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
995 resp = {getRound(), 0, {}};
997 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
1001 resp = {getRound(), 0, {
Vote()}};
1003 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1010 invs = getInvsForNextPoll();
1013 item = provider.buildVoteItem();
1014 itemid = provider.getVoteItemId(item);
1017 invs = getInvsForNextPoll();
1021 uint64_t queryRound = getRound();
1024 resp = {queryRound + 1, 0, {
Vote()}};
1025 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1027 resp = {queryRound - 1, 0, {
Vote()}};
1028 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1032 resp = {queryRound, 0, {
Vote(0, itemid)}};
1033 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1036 resp = {queryRound, 0, {
Vote(0, itemid)}};
1037 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1042 const auto item2 = provider.buildVoteItem();
1045 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1046 resp = {getRound(), 0, {votes[1], votes[0]}};
1048 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1052 resp = {getRound(), 0, votes};
1054 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1061 const uint32_t invType = provider.invType;
1063 auto itemA = provider.buildVoteItem();
1064 auto itemB = provider.buildVoteItem();
1066 auto avanodes = ConnectNodes();
1067 int nextNodeIndex = 0;
1070 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1076 auto invs = getInvsForNextPoll();
1078 for (
size_t i = 0; i < invs.size(); i++) {
1084 provider.invalidateItem(itemB);
1086 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1087 std::vector<avalanche::VoteItemUpdate> updates;
1090 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1091 goodResp, updates));
1095 invs = getInvsForNextPoll();
1098 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1101 Response badResp{getRound(), 0, votes};
1105 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1106 badResp, updates, error));
1110 votes = provider.buildVotesForItems(1, {itemA});
1111 auto registerNewVote = [&]() {
1112 Response resp = {getRound(), 0, votes};
1114 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1115 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1117 for (
size_t i = 0; i < 4000; i++) {
1119 if (updates.size() > 0 &&
1120 updates[0].getStatus() == VoteStatus::Invalid) {
1126 invs = getInvsForNextPoll();
1130 badResp =
Response(getRound(), 0, votes);
1133 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1134 badResp, updates, error));
1138BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1143 auto queryTimeDuration = std::chrono::milliseconds(10);
1144 setArg(
"-avatimeout",
ToString(queryTimeDuration.count()));
1146 setArg(
"-avalanchestakingpreconsensus",
"0");
1149 m_node.avalanche = Processor::MakeProcessor(
1153 const auto item = provider.buildVoteItem();
1154 const auto itemid = provider.getVoteItemId(item);
1164 for (
int i = 0; i < 10; i++) {
1166 avanodeid = getSuitableNodeToQuery();
1168 auto start = Now<SteadyMilliseconds>();
1172 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1175 std::vector<avalanche::VoteItemUpdate> updates;
1176 bool ret = registerVotes(avanodeid, next(resp), updates);
1177 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1188 avanodeid = getSuitableNodeToQuery();
1192 std::this_thread::sleep_for(queryTimeDuration);
1194 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1200 const uint32_t invType = provider.invType;
1203 auto proof = GetProof();
1207 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1208 for (
auto &n : nodes) {
1214 const auto item = provider.buildVoteItem();
1215 const auto itemid = provider.getVoteItemId(item);
1219 std::map<NodeId, uint64_t> node_round_map;
1221 NodeId nodeid = getSuitableNodeToQuery();
1222 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1223 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1224 auto invs = getInvsForNextPoll();
1232 auto suitablenodeid = getSuitableNodeToQuery();
1234 auto invs = getInvsForNextPoll();
1240 auto it = node_round_map.begin();
1242 std::vector<avalanche::VoteItemUpdate> updates;
1243 BOOST_CHECK(registerVotes(it->first, resp, updates));
1244 node_round_map.erase(it);
1246 invs = getInvsForNextPoll();
1253 std::vector<VoteItemUpdate> updates;
1255 CBlock block = CreateAndProcessBlock({}, CScript());
1261 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1265 auto avanodes = ConnectNodes();
1274 uint64_t round = getRound();
1278 for (
size_t i = 0; i < avanodes.size(); i++) {
1280 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1284 const NodeId firstNodeId = getSuitableNodeToQuery();
1285 std::map<NodeId, uint64_t> node_round_map;
1287 for (
size_t i = 0; i < avanodes.size(); i++) {
1288 NodeId nodeid = getSuitableNodeToQuery();
1289 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1290 node_round_map[nodeid] = getRound();
1296 auto confidence =
m_node.avalanche->getConfidence(pindex);
1297 BOOST_REQUIRE(confidence > 0);
1299 for (
auto &[nodeid, r] : node_round_map) {
1300 if (nodeid == firstNodeId) {
1307 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1312 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1319 CBlock block = CreateAndProcessBlock({}, CScript());
1325 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1332 std::chrono::steady_clock::time_point start,
stop;
1342 auto avanodes = ConnectNodes();
1345 NodeId nodeid = getSuitableNodeToQuery();
1346 BOOST_CHECK_NE(nodeid,
NO_NODE);
1349 uint64_t queryRound = getRound();
1353 for (
int i = 0; i < 60 * 1000; i++) {
1357 if (getRound() == queryRound + avanodes.size()) {
1366 uint64_t responseRound = getRound();
1367 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1369 std::vector<VoteItemUpdate> updates;
1371 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1374 for (
int i = 0; i < 10000; i++) {
1377 if (getRound() != responseRound) {
1378 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1397 schedulerThread.join();
1402 std::chrono::steady_clock::time_point start,
stop;
1404 std::thread schedulerThread;
1414 m_node.avalanche.reset();
1421 schedulerThread.join();
1428 auto addProofToReconcile = [&](uint32_t proofScore) {
1438 auto proof = addProofToReconcile(++score);
1440 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1449 for (
size_t i = 0; i < 10; i++) {
1450 auto proof = addProofToReconcile(++score);
1452 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1457 lastProofId = proof->
getId();
1460 for (
size_t i = 0; i < 10; i++) {
1461 auto proof = addProofToReconcile(--score);
1463 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1472 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1474 for (
auto &inv : invs) {
1475 BOOST_CHECK_NE(inv.hash, proof->
getId());
1481 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1482 setArg(
"-avalancheconflictingproofcooldown",
"0");
1496 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1497 coins.
AddCoin(conflictingOutpoint,
1500 coins.
AddCoin(immatureOutpoint,
1505 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1506 uint32_t height = 10) {
1513 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1514 auto validProof = buildProof(conflictingOutpoint, 2);
1515 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1566 int minStake = 400'000'000;
1567 setArg(
"-avaminquorumstake",
ToString(minStake));
1568 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1572 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1580 setArg(
"-avaproof", localProof->ToHex());
1584 m_node.avalanche = Processor::MakeProcessor(
1591 localProof->getId());
1595 AvalancheTest::getMinQuorumConnectedScoreRatio(*
m_node.avalanche), 0.5);
1617 for (
NodeId id = 0;
id < 8;
id++) {
1636 const int64_t tipTime =
1640 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1641 const int height = 100;
1642 const bool isCoinbase =
false;
1649 height, isCoinbase),
1654 auto proof2 = pb.
build();
1684 m_node.avalanche->withPeerManager(
1696 auto spendProofUtxo = [&](
ProofRef proof) {
1709 for (int64_t i = 0; i < 6; i++) {
1711 CreateAndProcessBlock({}, CScript());
1715 ->GetMedianTimePast(),
1716 proof2->getExpirationTime());
1727 spendProofUtxo(proof1);
1734 spendProofUtxo(
m_node.avalanche->getLocalProof());
1746 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1749 {
"",
"",
"",
false},
1750 {
"-1",
"-1",
"-1",
false},
1753 {
"-1",
"0",
"0",
false},
1754 {
"-0.01",
"0",
"0",
false},
1755 {
"21000000000000.01",
"0",
"0",
false},
1758 {
"0",
"-1",
"0",
false},
1759 {
"0",
"1.1",
"0",
false},
1762 {
"0",
"0",
"-1",
false},
1765 {
"0",
"0",
"0",
true},
1766 {
"0.00",
"0",
"0",
true},
1767 {
"0.01",
"0",
"0",
true},
1768 {
"1",
"0.1",
"0",
true},
1769 {
"10",
"0.5",
"0",
true},
1770 {
"10",
"1",
"0",
true},
1771 {
"21000000000000.00",
"0",
"0",
true},
1772 {
"0",
"0",
"1",
true},
1773 {
"0",
"0",
"100",
true},
1778 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1780 setArg(
"-avaminquorumstake", stake);
1781 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1782 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1785 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1805 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1806 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1809 auto processor = Processor::MakeProcessor(
1813 auto addNode = [&](
NodeId nodeid) {
1827 for (
NodeId id = 100;
id < 108;
id++) {
1832 minAvaproofsMessages <= 0);
1834 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1837 processor->avaproofsSent(i);
1841 processor->avaproofsSent(i);
1847 addNode(minAvaproofsMessages);
1848 processor->avaproofsSent(minAvaproofsMessages);
1852 AvalancheTest::clearavaproofsNodeCounter(*processor);
1856 checkMinAvaproofsMessages(0);
1857 checkMinAvaproofsMessages(1);
1858 checkMinAvaproofsMessages(10);
1859 checkMinAvaproofsMessages(100);
1864 setArg(
"-avastalevotethreshold",
1866 setArg(
"-avastalevotefactor",
"2");
1868 setArg(
"-avalanchestakingpreconsensus",
"0");
1870 const std::vector<std::tuple<int, int>> testCases = {
1877 m_node.avalanche = Processor::MakeProcessor(
1886 const uint32_t invType = provider.invType;
1888 const auto item = provider.buildVoteItem();
1889 const auto itemid = provider.getVoteItemId(item);
1892 auto avanodes = ConnectNodes();
1893 int nextNodeIndex = 0;
1895 std::vector<avalanche::VoteItemUpdate> updates;
1896 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
1899 auto invs = getInvsForNextPoll();
1906 auto registerNewVote = [&](
const Response &resp) {
1908 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1909 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1913 for (
int i = 0; i < numYesVotes; i++) {
1915 registerNewVote(next(resp));
1918 i >= 6 ? i - 5 : 0);
1923 for (
int i = 0; i < numNeutralVotes; i++) {
1925 registerNewVote(next(resp));
1930 invs = getInvsForNextPoll();
1937 registerNewVote(next(resp));
1939 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
1940 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
1943 invs = getInvsForNextPoll();
1949 BlockProvider provider(
this);
1953 std::vector<CBlockIndex *> blockIndexes;
1957 blockIndexes.push_back(pindex);
1960 auto invs = getInvsForNextPoll();
1974 std::vector<Vote> votes;
1977 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
1978 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
1981 auto avanodes = ConnectNodes();
1982 int nextNodeIndex = 0;
1984 std::vector<avalanche::VoteItemUpdate> updates;
1985 auto registerNewVote = [&]() {
1986 Response resp = {getRound(), 0, votes};
1988 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1989 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1995 bool eleventhBlockFinalized =
false;
1996 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
1999 for (
auto &update : updates) {
2000 if (update.getStatus() == VoteStatus::Finalized &&
2001 provider.fromAnyVoteItem(update.getVoteItem())
2002 ->GetBlockHash() == eleventhBlockHash) {
2003 eleventhBlockFinalized =
true;
2014 clearInvsNotWorthPolling();
2015 invs = getInvsForNextPoll();
2017 for (
size_t i = 0; i < 10; i++) {
2032 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2034 activeChainstate.InvalidateBlock(state, tip);
2037 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2040 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2048 activeChainstate.ResetBlockFailureFlags(tip);
2050 activeChainstate.ActivateBestChain(state);
2054 clearInvsNotWorthPolling();
2055 invs = getInvsForNextPoll();
2062 for (
auto &inv : invs) {
2063 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2066 bool tipFinalized =
false;
2067 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2070 for (
auto &update : updates) {
2071 if (update.getStatus() == VoteStatus::Finalized &&
2072 provider.fromAnyVoteItem(update.getVoteItem())
2073 ->GetBlockHash() == tiphash) {
2074 tipFinalized =
true;
2083 clearInvsNotWorthPolling();
2084 invs = getInvsForNextPoll();
2092 BlockHash alttiphash = alttip->GetBlockHash();
2093 votes = {{1, alttiphash}};
2095 bool alttipInvalidated =
false;
2096 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2099 for (
auto &update : updates) {
2100 if (update.getStatus() == VoteStatus::Invalid &&
2101 provider.fromAnyVoteItem(update.getVoteItem())
2102 ->GetBlockHash() == alttiphash) {
2103 alttipInvalidated =
true;
2108 invs = getInvsForNextPoll();
2119 const int numberElementsEachType = 100;
2122 std::vector<ProofRef> proofs;
2123 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2127 proofs.emplace_back(std::move(proof));
2129 Shuffle(proofs.begin(), proofs.end(), rng);
2131 std::vector<CBlockIndex> indexes;
2132 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2135 indexes.emplace_back(std::move(index));
2137 Shuffle(indexes.begin(), indexes.end(), rng);
2139 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2140 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2146 for (
size_t i = 0; i < numberElementsEachType; i++) {
2148 const size_t firstType = rng.
randrange(numTypes);
2150 for (
size_t j = 0; j < numTypes; j++) {
2151 switch ((firstType + j) % numTypes) {
2154 writeView->insert(std::make_pair(
2155 std::get<0>(allItems)[i],
VoteRecord(
true)));
2159 writeView->insert(std::make_pair(
2160 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2171 auto readView = voteMap.getReadView();
2172 auto it = readView.begin();
2175 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2176 for (
size_t i = 0; i < numberElementsEachType; i++) {
2177 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2179 uint32_t currentScore =
2180 std::get<const ProofRef>(it->first)->getScore();
2181 BOOST_CHECK_LT(currentScore, lastScore);
2182 lastScore = currentScore;
2190 for (
size_t i = 0; i < numberElementsEachType; i++) {
2191 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2194 std::get<const CBlockIndex *>(it->first)->nChainWork;
2196 lastWork = currentWork;
2209 const auto block = std::make_shared<const CBlock>(
2210 this->CreateBlock({}, CScript(), chainstate));
2237 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
2250 auto now = GetTime<std::chrono::seconds>();
2256 std::vector<CScript> winners;
2259 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2264 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2269 prevBlock.
nTime = now.count();
2274 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2277 size_t numProofs = 10;
2278 std::vector<ProofRef> proofs;
2279 proofs.reserve(numProofs);
2280 for (
size_t i = 0; i < numProofs; i++) {
2284 auto proof = GetProof(payoutScript);
2291 return pm.setFinalized(peer.peerid);
2295 proofs.emplace_back(std::move(proof));
2303 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2306 auto winnerExists = [&](
const CScript &expectedWinner) {
2307 const std::string winnerString =
FormatScript(expectedWinner);
2309 for (
const ProofRef &proof : proofs) {
2320 prevBlock.
nTime = now.count();
2325 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2331 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2337 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2341 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2346 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2350 m_node.avalanche->cleanupStakingRewards(101);
2354 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2358 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2364 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2368 m_node.avalanche->cleanupStakingRewards(200);
2372 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2374 !
m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2386 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2392 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2400 auto localProof = buildProof(outpoint, 1, 100);
2403 setArg(
"-avaproof", localProof->ToHex());
2404 setArg(
"-avalancheconflictingproofcooldown",
"0");
2405 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2406 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2410 m_node.avalanche = Processor::MakeProcessor(
2415 localProof->getId());
2417 auto checkLocalProofState = [&](
const bool boundToPeer,
2422 return pm.isBoundToPeer(localProof->getId());
2425 BOOST_CHECK_MESSAGE(
2426 m_node.avalanche->getLocalProofRegistrationState().GetResult() ==
2428 m_node.avalanche->getLocalProofRegistrationState().ToString());
2435 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2439 AvalancheTest::setLocalProofShareable(*
m_node.avalanche,
true);
2441 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2442 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2446 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2447 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2451 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2455 auto conflictingProof = buildProof(outpoint, 2, 100);
2461 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2462 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2466 setArg(
"-avalancheconflictingproofcooldown",
"0");
2467 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2487 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2494 auto proof = buildProof(outpoint, 1);
2513 AvalancheTest::addProofToRecentfinalized(*
m_node.avalanche, proof->
getId());
2520 return peer.hasFinalized;
2527 auto betterProof = buildProof(outpoint, 2);
2550 m_node.avalanche = Processor::MakeProcessor(
2556 auto now = GetTime<std::chrono::seconds>();
2559 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
true);
2567 const ProofId proofid1 = proof1->getId();
2572 const ProofId proofid2 = proof2->getId();
2583 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2585 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2591 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2596 for (
NodeId n = 0; n < 8; n++) {
2601 return pm.setFinalized(peer.peerid);
2610 CBlock block = CreateAndProcessBlock({}, CScript());
2613 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2614 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2620 std::vector<CScript> winners;
2624 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2629 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2633 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2635 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2641 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2647 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2655 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2658 m_node.avalanche->getStakeContenderStatus(contender1_block1), -1);
2660 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2663 m_node.avalanche->getStakeContenderStatus(contender2_block1), -1);
2665 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2668 m_node.avalanche->setStakingRewardWinners(
2669 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2674 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2677 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2680 m_node.avalanche->withPeerManager(
2686 const ProofId proofid3 = proof3->getId();
2689 for (
NodeId n = 0; n < 8; n++) {
2695 block = CreateAndProcessBlock({}, CScript());
2698 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2699 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2703 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2707 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2709 m_node.avalanche->getStakeContenderStatus(contender2_block2), -1);
2716 m_node.avalanche->getStakeContenderStatus(contender1_block3), -1);
2720 m_node.avalanche->getStakeContenderStatus(contender2_block3), -1);
2723 m_node.avalanche->withPeerManager(
2727 size_t numProofs = 8;
2728 std::vector<ProofRef> proofs;
2729 proofs.reserve(numProofs);
2730 for (
size_t i = 0; i < numProofs; i++) {
2739 return pm.setFinalized(peer.peerid);
2742 proofs.emplace_back(std::move(proof));
2747 const ProofId proofid = proofs[0]->getId();
2748 for (
NodeId n = 0; n < 8; n++) {
2758 std::vector<CScript> winners;
2759 for (
int attempt = 0; attempt < 10; attempt++) {
2761 block = CreateAndProcessBlock({}, CScript());
2764 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2765 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2771 chaintip->GetBlockHash(), winners));
2772 if (winners.size() == 8) {
2780 size_t numAccepted = 0;
2781 for (
const auto &proof : proofs) {
2785 if (
m_node.avalanche->getStakeContenderStatus(contender) == 0) {
2787 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2795 block = CreateAndProcessBlock({}, CScript());
2798 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2803 m_node.avalanche->withPeerManager(
2805 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2814 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2815 bestproof->getPayoutScript()) == winners.end());
2822 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2833 block = CreateAndProcessBlock({}, CScript());
2836 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2837 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2838 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
2845 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2859 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2860 bestproof->getPayoutScript()) == winners.end());
2868 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2879 auto now = GetTime<std::chrono::seconds>();
2883 auto localWinnerProof =
2885 ProofId localWinnerProofId = localWinnerProof->getId();
2887 localWinnerProof->getId());
2896 for (
NodeId n = 0; n < 8; n++) {
2897 pm.
addNode(n, localWinnerProofId,
2901 return pm.setFinalized(peer.peerid);
2908 chaintip->
nTime = now.count();
2914 std::vector<ProofRef> acceptedContenderProofs;
2915 acceptedContenderProofs.push_back(localWinnerProof);
2922 for (
size_t numContenders = 2;
2926 m_node.avalanche->withPeerManager(
2932 if (rank <= bestRank) {
2934 acceptedContenderProofs.push_back(proof);
2935 const size_t numAccepted =
2937 acceptedContenderProofs.size());
2938 std::sort(acceptedContenderProofs.begin(),
2939 acceptedContenderProofs.begin() + numAccepted,
2941 const ProofId leftProofId = left->getId();
2942 const ProofId rightProofId = right->getId();
2943 const StakeContenderId leftContenderId(chaintipHash,
2945 const StakeContenderId rightContenderId(chaintipHash,
2947 return RewardRankComparator()(
2949 leftContenderId.ComputeProofRewardRank(
2950 MIN_VALID_PROOF_SCORE),
2951 leftProofId, rightContenderId,
2952 rightContenderId.ComputeProofRewardRank(
2953 MIN_VALID_PROOF_SCORE),
2958 std::vector<StakeContenderId> pollableContenders;
2959 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
2960 *
m_node.avalanche, chaintip, pollableContenders));
2962 pollableContenders.size(),
2967 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
2971 chaintipHash, acceptedContenderProofs[i]->getId());
2973 std::find(pollableContenders.begin(), pollableContenders.end(),
2974 acceptedContenderId) != pollableContenders.end());
2976 m_node.avalanche->getStakeContenderStatus(acceptedContenderId),
2981 std::set<StakeContenderId> unacceptedContenderIds(
2982 pollableContenders.begin(), pollableContenders.end());
2983 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
2985 chaintipHash, acceptedContenderProof->getId());
2986 unacceptedContenderIds.erase(acceptedContenderId);
2989 for (
auto cid : unacceptedContenderIds) {
2996 m_node.avalanche->getStakeContenderStatus(localWinnerContenderId),
3001BOOST_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 addNode(NodeId nodeid, const ProofId &proofid, size_t max_elements)
Node API.
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
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.
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::vector< CInv > getInvsForNextPoll(RWCollection< VoteMap >::ReadView &voteRecordsReadView, size_t max_elements, bool forPoll=true) const
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 DEFAULT_AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
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 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.