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");
1150 m_node.avalanche = Processor::MakeProcessor(
1154 const auto item = provider.buildVoteItem();
1155 const auto itemid = provider.getVoteItemId(item);
1165 for (
int i = 0; i < 10; i++) {
1167 avanodeid = getSuitableNodeToQuery();
1169 auto start = Now<SteadyMilliseconds>();
1173 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1176 std::vector<avalanche::VoteItemUpdate> updates;
1177 bool ret = registerVotes(avanodeid, next(resp), updates);
1178 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1189 avanodeid = getSuitableNodeToQuery();
1193 std::this_thread::sleep_for(queryTimeDuration);
1195 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1201 const uint32_t invType = provider.invType;
1204 auto proof = GetProof();
1208 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1209 for (
auto &n : nodes) {
1215 const auto item = provider.buildVoteItem();
1216 const auto itemid = provider.getVoteItemId(item);
1220 std::map<NodeId, uint64_t> node_round_map;
1222 NodeId nodeid = getSuitableNodeToQuery();
1223 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1224 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1225 auto invs = getInvsForNextPoll();
1233 auto suitablenodeid = getSuitableNodeToQuery();
1235 auto invs = getInvsForNextPoll();
1241 auto it = node_round_map.begin();
1243 std::vector<avalanche::VoteItemUpdate> updates;
1244 BOOST_CHECK(registerVotes(it->first, resp, updates));
1245 node_round_map.erase(it);
1247 invs = getInvsForNextPoll();
1254 std::vector<VoteItemUpdate> updates;
1256 CBlock block = CreateAndProcessBlock({}, CScript());
1262 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1266 auto avanodes = ConnectNodes();
1275 uint64_t round = getRound();
1279 for (
size_t i = 0; i < avanodes.size(); i++) {
1281 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1285 const NodeId firstNodeId = getSuitableNodeToQuery();
1286 std::map<NodeId, uint64_t> node_round_map;
1288 for (
size_t i = 0; i < avanodes.size(); i++) {
1289 NodeId nodeid = getSuitableNodeToQuery();
1290 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1291 node_round_map[nodeid] = getRound();
1297 auto confidence =
m_node.avalanche->getConfidence(pindex);
1298 BOOST_REQUIRE(confidence > 0);
1300 for (
auto &[nodeid, r] : node_round_map) {
1301 if (nodeid == firstNodeId) {
1308 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1313 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1320 CBlock block = CreateAndProcessBlock({}, CScript());
1326 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1333 std::chrono::steady_clock::time_point start,
stop;
1343 auto avanodes = ConnectNodes();
1346 NodeId nodeid = getSuitableNodeToQuery();
1347 BOOST_CHECK_NE(nodeid,
NO_NODE);
1350 uint64_t queryRound = getRound();
1354 for (
int i = 0; i < 60 * 1000; i++) {
1358 if (getRound() == queryRound + avanodes.size()) {
1367 uint64_t responseRound = getRound();
1368 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1370 std::vector<VoteItemUpdate> updates;
1372 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1375 for (
int i = 0; i < 10000; i++) {
1378 if (getRound() != responseRound) {
1379 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1398 schedulerThread.join();
1403 std::chrono::steady_clock::time_point start,
stop;
1405 std::thread schedulerThread;
1416 m_node.avalanche.reset();
1423 schedulerThread.join();
1430 auto addProofToReconcile = [&](uint32_t proofScore) {
1440 auto proof = addProofToReconcile(++score);
1442 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1451 for (
size_t i = 0; i < 10; i++) {
1452 auto proof = addProofToReconcile(++score);
1454 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1459 lastProofId = proof->
getId();
1462 for (
size_t i = 0; i < 10; i++) {
1463 auto proof = addProofToReconcile(--score);
1465 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1474 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1476 for (
auto &inv : invs) {
1477 BOOST_CHECK_NE(inv.hash, proof->
getId());
1483 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1484 setArg(
"-avalancheconflictingproofcooldown",
"0");
1498 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1499 coins.
AddCoin(conflictingOutpoint,
1502 coins.
AddCoin(immatureOutpoint,
1507 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1508 uint32_t height = 10) {
1515 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1516 auto validProof = buildProof(conflictingOutpoint, 2);
1517 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1568 int minStake = 400'000'000;
1569 setArg(
"-avaminquorumstake",
ToString(minStake));
1570 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1574 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1582 setArg(
"-avaproof", localProof->ToHex());
1587 m_node.avalanche = Processor::MakeProcessor(
1594 localProof->getId());
1598 AvalancheTest::getMinQuorumConnectedScoreRatio(*
m_node.avalanche), 0.5);
1620 for (
NodeId id = 0;
id < 8;
id++) {
1639 const int64_t tipTime =
1643 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1644 const int height = 100;
1645 const bool isCoinbase =
false;
1652 height, isCoinbase),
1657 auto proof2 = pb.
build();
1687 m_node.avalanche->withPeerManager(
1699 auto spendProofUtxo = [&](
ProofRef proof) {
1712 for (int64_t i = 0; i < 6; i++) {
1714 CreateAndProcessBlock({}, CScript());
1718 ->GetMedianTimePast(),
1719 proof2->getExpirationTime());
1730 spendProofUtxo(proof1);
1737 spendProofUtxo(
m_node.avalanche->getLocalProof());
1749 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1752 {
"",
"",
"",
false},
1753 {
"-1",
"-1",
"-1",
false},
1756 {
"-1",
"0",
"0",
false},
1757 {
"-0.01",
"0",
"0",
false},
1758 {
"21000000000000.01",
"0",
"0",
false},
1761 {
"0",
"-1",
"0",
false},
1762 {
"0",
"1.1",
"0",
false},
1765 {
"0",
"0",
"-1",
false},
1768 {
"0",
"0",
"0",
true},
1769 {
"0.00",
"0",
"0",
true},
1770 {
"0.01",
"0",
"0",
true},
1771 {
"1",
"0.1",
"0",
true},
1772 {
"10",
"0.5",
"0",
true},
1773 {
"10",
"1",
"0",
true},
1774 {
"21000000000000.00",
"0",
"0",
true},
1775 {
"0",
"0",
"1",
true},
1776 {
"0",
"0",
"100",
true},
1781 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1783 setArg(
"-avaminquorumstake", stake);
1784 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1785 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1788 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1808 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1809 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1812 auto processor = Processor::MakeProcessor(
1816 auto addNode = [&](
NodeId nodeid) {
1830 for (
NodeId id = 100;
id < 108;
id++) {
1835 minAvaproofsMessages <= 0);
1837 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1840 processor->avaproofsSent(i);
1844 processor->avaproofsSent(i);
1850 addNode(minAvaproofsMessages);
1851 processor->avaproofsSent(minAvaproofsMessages);
1855 AvalancheTest::clearavaproofsNodeCounter(*processor);
1859 checkMinAvaproofsMessages(0);
1860 checkMinAvaproofsMessages(1);
1861 checkMinAvaproofsMessages(10);
1862 checkMinAvaproofsMessages(100);
1867 setArg(
"-avastalevotethreshold",
1869 setArg(
"-avastalevotefactor",
"2");
1871 setArg(
"-avalanchestakingpreconsensus",
"0");
1873 const std::vector<std::tuple<int, int>> testCases = {
1881 m_node.avalanche = Processor::MakeProcessor(
1890 const uint32_t invType = provider.invType;
1892 const auto item = provider.buildVoteItem();
1893 const auto itemid = provider.getVoteItemId(item);
1896 auto avanodes = ConnectNodes();
1897 int nextNodeIndex = 0;
1899 std::vector<avalanche::VoteItemUpdate> updates;
1900 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
1903 auto invs = getInvsForNextPoll();
1910 auto registerNewVote = [&](
const Response &resp) {
1912 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1913 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1917 for (
int i = 0; i < numYesVotes; i++) {
1919 registerNewVote(next(resp));
1922 i >= 6 ? i - 5 : 0);
1927 for (
int i = 0; i < numNeutralVotes; i++) {
1929 registerNewVote(next(resp));
1934 invs = getInvsForNextPoll();
1941 registerNewVote(next(resp));
1943 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
1944 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
1947 invs = getInvsForNextPoll();
1953 BlockProvider provider(
this);
1957 std::vector<CBlockIndex *> blockIndexes;
1961 blockIndexes.push_back(pindex);
1964 auto invs = getInvsForNextPoll();
1978 std::vector<Vote> votes;
1981 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
1982 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
1985 auto avanodes = ConnectNodes();
1986 int nextNodeIndex = 0;
1988 std::vector<avalanche::VoteItemUpdate> updates;
1989 auto registerNewVote = [&]() {
1990 Response resp = {getRound(), 0, votes};
1992 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1993 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1999 bool eleventhBlockFinalized =
false;
2000 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
2003 for (
auto &update : updates) {
2004 if (update.getStatus() == VoteStatus::Finalized &&
2005 provider.fromAnyVoteItem(update.getVoteItem())
2006 ->GetBlockHash() == eleventhBlockHash) {
2007 eleventhBlockFinalized =
true;
2018 clearInvsNotWorthPolling();
2019 invs = getInvsForNextPoll();
2021 for (
size_t i = 0; i < 10; i++) {
2036 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2038 activeChainstate.InvalidateBlock(state, tip);
2041 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2044 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2052 activeChainstate.ResetBlockFailureFlags(tip);
2054 activeChainstate.ActivateBestChain(state);
2058 clearInvsNotWorthPolling();
2059 invs = getInvsForNextPoll();
2066 for (
auto &inv : invs) {
2067 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2070 bool tipFinalized =
false;
2071 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2074 for (
auto &update : updates) {
2075 if (update.getStatus() == VoteStatus::Finalized &&
2076 provider.fromAnyVoteItem(update.getVoteItem())
2077 ->GetBlockHash() == tiphash) {
2078 tipFinalized =
true;
2087 clearInvsNotWorthPolling();
2088 invs = getInvsForNextPoll();
2096 BlockHash alttiphash = alttip->GetBlockHash();
2097 votes = {{1, alttiphash}};
2099 bool alttipInvalidated =
false;
2100 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2103 for (
auto &update : updates) {
2104 if (update.getStatus() == VoteStatus::Invalid &&
2105 provider.fromAnyVoteItem(update.getVoteItem())
2106 ->GetBlockHash() == alttiphash) {
2107 alttipInvalidated =
true;
2112 invs = getInvsForNextPoll();
2123 const int numberElementsEachType = 100;
2126 std::vector<ProofRef> proofs;
2127 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2131 proofs.emplace_back(std::move(proof));
2133 Shuffle(proofs.begin(), proofs.end(), rng);
2135 std::vector<CBlockIndex> indexes;
2136 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2139 indexes.emplace_back(std::move(index));
2141 Shuffle(indexes.begin(), indexes.end(), rng);
2143 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2144 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2150 for (
size_t i = 0; i < numberElementsEachType; i++) {
2152 const size_t firstType = rng.
randrange(numTypes);
2154 for (
size_t j = 0; j < numTypes; j++) {
2155 switch ((firstType + j) % numTypes) {
2158 writeView->insert(std::make_pair(
2159 std::get<0>(allItems)[i],
VoteRecord(
true)));
2163 writeView->insert(std::make_pair(
2164 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2175 auto readView = voteMap.getReadView();
2176 auto it = readView.begin();
2179 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2180 for (
size_t i = 0; i < numberElementsEachType; i++) {
2181 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2183 uint32_t currentScore =
2184 std::get<const ProofRef>(it->first)->getScore();
2185 BOOST_CHECK_LT(currentScore, lastScore);
2186 lastScore = currentScore;
2194 for (
size_t i = 0; i < numberElementsEachType; i++) {
2195 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2198 std::get<const CBlockIndex *>(it->first)->nChainWork;
2200 lastWork = currentWork;
2213 const auto block = std::make_shared<const CBlock>(
2214 this->CreateBlock({}, CScript(), chainstate));
2241 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
2251 auto now = GetTime<std::chrono::seconds>();
2257 std::vector<CScript> winners;
2260 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2265 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2270 prevBlock.
nTime = now.count();
2275 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2278 size_t numProofs = 10;
2279 std::vector<ProofRef> proofs;
2280 proofs.reserve(numProofs);
2281 for (
size_t i = 0; i < numProofs; i++) {
2285 auto proof = GetProof(payoutScript);
2292 return pm.setFinalized(peer.peerid);
2296 proofs.emplace_back(std::move(proof));
2304 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2307 auto winnerExists = [&](
const CScript &expectedWinner) {
2308 const std::string winnerString =
FormatScript(expectedWinner);
2310 for (
const ProofRef &proof : proofs) {
2321 prevBlock.
nTime = now.count();
2326 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2332 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2338 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2342 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2347 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2351 m_node.avalanche->cleanupStakingRewards(101);
2355 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2359 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2365 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2369 m_node.avalanche->cleanupStakingRewards(200);
2373 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2375 !
m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2387 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2393 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2401 auto localProof = buildProof(outpoint, 1, 100);
2404 setArg(
"-avaproof", localProof->ToHex());
2405 setArg(
"-avalancheconflictingproofcooldown",
"0");
2406 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2407 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2412 m_node.avalanche = Processor::MakeProcessor(
2417 localProof->getId());
2419 auto checkLocalProofState = [&](
const bool boundToPeer,
2424 return pm.isBoundToPeer(localProof->getId());
2427 BOOST_CHECK_MESSAGE(
2428 m_node.avalanche->getLocalProofRegistrationState().GetResult() ==
2430 m_node.avalanche->getLocalProofRegistrationState().ToString());
2437 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2441 AvalancheTest::setLocalProofShareable(*
m_node.avalanche,
true);
2443 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2444 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2448 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2449 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2453 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2457 auto conflictingProof = buildProof(outpoint, 2, 100);
2463 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2464 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2468 setArg(
"-avalancheconflictingproofcooldown",
"0");
2469 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2489 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2496 auto proof = buildProof(outpoint, 1);
2515 AvalancheTest::addProofToRecentfinalized(*
m_node.avalanche, proof->
getId());
2522 return peer.hasFinalized;
2529 auto betterProof = buildProof(outpoint, 2);
2553 m_node.avalanche = Processor::MakeProcessor(
2559 auto now = GetTime<std::chrono::seconds>();
2562 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
true);
2570 const ProofId proofid1 = proof1->getId();
2575 const ProofId proofid2 = proof2->getId();
2586 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2588 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2594 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2599 for (
NodeId n = 0; n < 8; n++) {
2604 return pm.setFinalized(peer.peerid);
2613 CBlock block = CreateAndProcessBlock({}, CScript());
2616 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2617 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2623 std::vector<CScript> winners;
2627 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2632 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2636 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2638 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2644 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2650 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2658 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2661 m_node.avalanche->getStakeContenderStatus(contender1_block1), -1);
2663 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2666 m_node.avalanche->getStakeContenderStatus(contender2_block1), -1);
2668 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2671 m_node.avalanche->setStakingRewardWinners(
2672 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2677 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2680 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2683 m_node.avalanche->withPeerManager(
2689 const ProofId proofid3 = proof3->getId();
2692 for (
NodeId n = 0; n < 8; n++) {
2698 block = CreateAndProcessBlock({}, CScript());
2701 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2702 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2706 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2710 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2712 m_node.avalanche->getStakeContenderStatus(contender2_block2), -1);
2719 m_node.avalanche->getStakeContenderStatus(contender1_block3), -1);
2723 m_node.avalanche->getStakeContenderStatus(contender2_block3), -1);
2726 m_node.avalanche->withPeerManager(
2730 size_t numProofs = 8;
2731 std::vector<ProofRef> proofs;
2732 proofs.reserve(numProofs);
2733 for (
size_t i = 0; i < numProofs; i++) {
2742 return pm.setFinalized(peer.peerid);
2745 proofs.emplace_back(std::move(proof));
2750 const ProofId proofid = proofs[0]->getId();
2751 for (
NodeId n = 0; n < 8; n++) {
2761 std::vector<CScript> winners;
2762 for (
int attempt = 0; attempt < 10; attempt++) {
2764 block = CreateAndProcessBlock({}, CScript());
2767 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2768 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2774 chaintip->GetBlockHash(), winners));
2775 if (winners.size() == 8) {
2783 size_t numAccepted = 0;
2784 for (
const auto &proof : proofs) {
2788 if (
m_node.avalanche->getStakeContenderStatus(contender) == 0) {
2790 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2798 block = CreateAndProcessBlock({}, CScript());
2801 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2806 m_node.avalanche->withPeerManager(
2808 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2817 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2818 bestproof->getPayoutScript()) == winners.end());
2825 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2836 block = CreateAndProcessBlock({}, CScript());
2839 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2840 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2841 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
2848 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2862 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2863 bestproof->getPayoutScript()) == winners.end());
2871 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2882 auto now = GetTime<std::chrono::seconds>();
2886 auto localWinnerProof =
2888 ProofId localWinnerProofId = localWinnerProof->getId();
2890 localWinnerProof->getId());
2899 for (
NodeId n = 0; n < 8; n++) {
2900 pm.
addNode(n, localWinnerProofId,
2904 return pm.setFinalized(peer.peerid);
2911 chaintip->
nTime = now.count();
2917 std::vector<ProofRef> acceptedContenderProofs;
2918 acceptedContenderProofs.push_back(localWinnerProof);
2925 for (
size_t numContenders = 2;
2929 m_node.avalanche->withPeerManager(
2935 if (rank <= bestRank) {
2937 acceptedContenderProofs.push_back(proof);
2938 const size_t numAccepted =
2940 acceptedContenderProofs.size());
2941 std::sort(acceptedContenderProofs.begin(),
2942 acceptedContenderProofs.begin() + numAccepted,
2944 const ProofId leftProofId = left->getId();
2945 const ProofId rightProofId = right->getId();
2946 const StakeContenderId leftContenderId(chaintipHash,
2948 const StakeContenderId rightContenderId(chaintipHash,
2950 return RewardRankComparator()(
2952 leftContenderId.ComputeProofRewardRank(
2953 MIN_VALID_PROOF_SCORE),
2954 leftProofId, rightContenderId,
2955 rightContenderId.ComputeProofRewardRank(
2956 MIN_VALID_PROOF_SCORE),
2961 std::vector<StakeContenderId> pollableContenders;
2962 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
2963 *
m_node.avalanche, chaintip, pollableContenders));
2965 pollableContenders.size(),
2970 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
2974 chaintipHash, acceptedContenderProofs[i]->getId());
2976 std::find(pollableContenders.begin(), pollableContenders.end(),
2977 acceptedContenderId) != pollableContenders.end());
2979 m_node.avalanche->getStakeContenderStatus(acceptedContenderId),
2984 std::set<StakeContenderId> unacceptedContenderIds(
2985 pollableContenders.begin(), pollableContenders.end());
2986 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
2988 chaintipHash, acceptedContenderProof->getId());
2989 unacceptedContenderIds.erase(acceptedContenderId);
2992 for (
auto cid : unacceptedContenderIds) {
2999 m_node.avalanche->getStakeContenderStatus(localWinnerContenderId),
3004BOOST_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.