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,
47 bool forPoll =
false) {
55 return p.peerManager->selectNode());
60 static uint32_t getMinQuorumScore(
const Processor &p) {
64 static double getMinQuorumConnectedScoreRatio(
const Processor &p) {
68 static void clearavaproofsNodeCounter(
Processor &p) {
75 std::make_pair(item, voteRecord));
82 static void setFinalizationTip(
Processor &p,
85 p.finalizationTip = pindex;
88 static void setLocalProofShareable(
Processor &p,
bool shareable) {
94 static void addProofToRecentfinalized(
Processor &p,
97 return p.finalizedItems.insert(proofid));
100 static bool setContenderStatusForLocalWinners(
102 std::vector<StakeContenderId> &pollableContenders) {
107 static void setStakingPreconsensus(
Processor &p,
bool enabled) {
111 static void clearInvsNotWorthPolling(
Processor &p) {
117 const std::map<CInv, uint8_t> &itemCounts) {
137struct AvalancheProcessorTestingSetup :
public AvalancheTestChain100Setup {
138 AvalancheProcessorTestingSetup() : AvalancheTestChain100Setup() {
139 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
false);
147 new CNode(
id++,
nullptr, addr,
154 node->m_has_all_wanted_services =
158 node->fSuccessfullyConnected =
true;
160 m_connman->AddTestNode(*
node);
169 const uint32_t height = 100;
178 BOOST_CHECK(pb.addUTXO(outpoint, amount, height,
false, key));
183 return m_node.avalanche->withPeerManager(
185 return pm.
addNode(nodeid, proofid,
190 bool addNode(
NodeId nodeid) {
191 auto proof = GetProof();
192 return m_node.avalanche->withPeerManager(
195 pm.
addNode(nodeid, proof->getId(),
200 std::array<CNode *, 8> ConnectNodes() {
201 auto proof = GetProof();
204 return pm.registerProof(proof);
206 const ProofId &proofid = proof->getId();
208 std::array<CNode *, 8> nodes;
209 for (
CNode *&n : nodes) {
217 void runEventLoop() { AvalancheTest::runEventLoop(*
m_node.avalanche); }
219 NodeId getSuitableNodeToQuery() {
220 return AvalancheTest::getSuitableNodeToQuery(*
m_node.avalanche);
223 std::vector<CInv> getInvsForNextPoll(
bool forPoll =
false) {
224 return AvalancheTest::getInvsForNextPoll(*
m_node.avalanche, forPoll);
227 uint64_t getRound()
const {
228 return AvalancheTest::getRound(*
m_node.avalanche);
232 std::vector<avalanche::VoteItemUpdate> &updates,
233 std::string &error) {
240 std::vector<avalanche::VoteItemUpdate> &updates) {
248 return m_node.avalanche->addToReconcile(item);
251 void clearInvsNotWorthPolling() {
252 AvalancheTest::clearInvsNotWorthPolling(*
m_node.avalanche);
255 void clearInflightRequests(
const std::map<CInv, uint8_t> &itemCounts) {
256 AvalancheTest::clearInflightRequests(*
m_node.avalanche, itemCounts);
260struct BlockProvider {
261 AvalancheProcessorTestingSetup *fixture;
264 BlockProvider(AvalancheProcessorTestingSetup *_fixture)
265 : fixture(_fixture) {}
268 CBlock block = fixture->CreateAndProcessBlock({}, CScript());
272 return Assert(fixture->m_node.chainman)
273 ->m_blockman.LookupBlockIndex(blockHash);
280 std::vector<Vote> buildVotesForItems(uint32_t error,
281 std::vector<CBlockIndex *> &&items) {
282 size_t numItems = items.
size();
284 std::vector<Vote> votes;
285 votes.reserve(numItems);
290 votes.emplace_back(error, item->GetBlockHash());
298 pindex->nStatus = pindex->nStatus.withFailed();
302 return std::get<const CBlockIndex *>(item);
306struct ProofProvider {
307 AvalancheProcessorTestingSetup *fixture;
310 ProofProvider(AvalancheProcessorTestingSetup *_fixture)
311 : fixture(_fixture) {}
314 ProofRef proof = fixture->GetProof();
315 fixture->m_node.avalanche->withPeerManager(
323 return proof->
getId();
326 std::vector<Vote> buildVotesForItems(uint32_t error,
327 std::vector<ProofRef> &&items) {
328 size_t numItems = items.
size();
330 std::vector<Vote> votes;
331 votes.reserve(numItems);
335 for (
auto &item : items) {
336 votes.emplace_back(error, item->getId());
342 void invalidateItem(
const ProofRef &proof) {
343 fixture->m_node.avalanche->withPeerManager(
352 return std::get<const ProofRef>(item);
356struct StakeContenderProvider {
357 AvalancheProcessorTestingSetup *fixture;
359 std::vector<avalanche::VoteItemUpdate> updates;
362 StakeContenderProvider(AvalancheProcessorTestingSetup *_fixture)
363 : fixture(_fixture) {}
370 std::vector<CScript> winners;
371 if (!fixture->m_node.avalanche->getStakingRewardWinners(
375 const ProofRef proofWinner = fixture->GetProof();
377 fixture->m_node.avalanche->setStakingRewardWinners(chaintip,
382 const ProofRef proof = fixture->GetProof();
386 fixture->m_node.avalanche->withPeerManager(
393 fixture->m_node.avalanche->acceptStakeContender(contenderId);
395 BOOST_CHECK(fixture->m_node.avalanche->getStakeContenderStatus(
405 buildVotesForItems(uint32_t error, std::vector<StakeContenderId> &&items) {
406 size_t numItems = items.
size();
408 std::vector<Vote> votes;
409 votes.reserve(numItems);
412 std::sort(items.begin(), items.end(),
416 for (
auto &item : items) {
417 votes.emplace_back(error, item);
424 fixture->m_node.avalanche->rejectStakeContender(contenderId);
432 AvalancheTest::removeVoteRecord(*(fixture->m_node.avalanche),
437 return std::get<const StakeContenderId>(item);
442 AvalancheProcessorTestingSetup *fixture;
444 std::vector<avalanche::VoteItemUpdate> updates;
447 TxProvider(AvalancheProcessorTestingSetup *_fixture) : fixture(_fixture) {}
457 TestMemPoolEntryHelper mempoolEntryHelper;
458 auto entry = mempoolEntryHelper.Fee(1000 *
SATOSHI).FromTx(tx);
474 std::vector<Vote> buildVotesForItems(uint32_t error,
475 std::vector<CTransactionRef> &&items) {
476 size_t numItems = items.
size();
478 std::vector<Vote> votes;
479 votes.reserve(numItems);
482 std::sort(items.begin(), items.end(),
484 return lhs->GetId() < rhs->GetId();
486 for (
auto &item : items) {
487 votes.emplace_back(error, item->GetId());
503 return std::get<const CTransactionRef>(item);
509BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheProcessorTestingSetup)
513 StakeContenderProvider, TxProvider>;
515 boost::mpl::list<BlockProvider, ProofProvider, TxProvider>;
524 std::set<VoteStatus> status{
525 VoteStatus::Invalid, VoteStatus::Rejected, VoteStatus::Accepted,
526 VoteStatus::Finalized, VoteStatus::Stale,
529 auto item = provider.buildVoteItem();
531 for (
auto s : status) {
554 auto item = provider.buildVoteItem();
555 auto itemid = provider.getVoteItemId(item);
564 auto avanodes = ConnectNodes();
566 int nextNodeIndex = 0;
567 std::vector<avalanche::VoteItemUpdate> updates;
568 auto registerNewVote = [&](
const Response &resp) {
570 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
572 bool vote_is_registered = registerVotes(nodeid, resp, updates, error);
573 BOOST_CHECK_MESSAGE(vote_is_registered,
574 "registerVotes failed with error: " << error);
578 auto finalize = [&](
const auto finalizeItemId) {
579 Response resp = {getRound(), 0, {
Vote(0, finalizeItemId)}};
581 registerNewVote(next(resp));
582 if (updates.size() > 0) {
587 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
588 m_node.avalanche->setRecentlyFinalized(finalizeItemId);
595 auto finalizeNewItem = [&]() {
596 auto anotherItem = provider.buildVoteItem();
598 auto anotherItemId = provider.getVoteItemId(anotherItem);
601 AvalancheTest::addVoteRecord(*
m_node.avalanche, anotherVoteItem,
603 finalize(anotherItemId);
623 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
636 auto item =
decltype(provider.buildVoteItem())();
643 item = provider.buildVoteItem();
654 auto itemZero =
decltype(provider.buildVoteItem())();
667 auto item = provider.buildVoteItem();
677 const uint32_t invType = provider.invType;
679 auto item = provider.buildVoteItem();
680 auto itemid = provider.getVoteItemId(item);
683 auto avanodes = ConnectNodes();
691 auto invs = getInvsForNextPoll();
699 int nextNodeIndex = 0;
700 std::vector<avalanche::VoteItemUpdate> updates;
701 auto registerNewVote = [&](
const Response &resp) {
703 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
709 for (
int i = 0; i < 6; i++) {
710 registerNewVote(next(resp));
717 resp = {getRound(), 0, {
Vote(-1, itemid)}};
718 registerNewVote(next(resp));
723 resp = {getRound(), 0, {
Vote(0, itemid)}};
724 for (
int i = 1; i < 7; i++) {
725 registerNewVote(next(resp));
732 resp = {getRound(), 0, {
Vote(-1, itemid)}};
733 registerNewVote(next(resp));
737 registerNewVote(next(resp));
742 resp = {getRound(), 0, {
Vote(0, itemid)}};
743 for (
int i = 2; i < 8; i++) {
744 registerNewVote(next(resp));
752 registerNewVote(next(resp));
759 invs = getInvsForNextPoll();
765 registerNewVote(next(resp));
767 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
768 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
771 invs = getInvsForNextPoll();
775 item = provider.buildVoteItem();
776 itemid = provider.getVoteItemId(item);
780 invs = getInvsForNextPoll();
785 resp = {getRound(), 0, {
Vote(1, itemid)}};
786 for (
int i = 0; i < 6; i++) {
787 registerNewVote(next(resp));
793 registerNewVote(next(resp));
796 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
797 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
801 registerNewVote(next(resp));
807 invs = getInvsForNextPoll();
813 registerNewVote(next(resp));
816 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
817 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
820 invs = getInvsForNextPoll();
826 const uint32_t invType = provider.invType;
828 auto itemA = provider.buildVoteItem();
829 auto itemidA = provider.getVoteItemId(itemA);
831 auto itemB = provider.buildVoteItem();
832 auto itemidB = provider.getVoteItemId(itemB);
835 auto avanodes = ConnectNodes();
843 auto invs = getInvsForNextPoll();
848 uint64_t round = getRound();
850 std::vector<avalanche::VoteItemUpdate> updates;
852 {round, 0, {
Vote(0, itemidA)}}, updates));
856 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
859 invs = getInvsForNextPoll();
863 for (
size_t i = 0; i < invs.size(); i++) {
869 for (
int i = 0; i < 4; i++) {
870 NodeId nodeid = getSuitableNodeToQuery();
872 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
878 NodeId nodeid = getSuitableNodeToQuery();
880 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
886 NodeId firstNodeid = getSuitableNodeToQuery();
888 NodeId secondNodeid = getSuitableNodeToQuery();
894 BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates));
896 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemA);
897 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
900 invs = getInvsForNextPoll();
906 BOOST_CHECK(registerVotes(secondNodeid, resp, updates));
908 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemB);
909 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
912 invs = getInvsForNextPoll();
918 const uint32_t invType = provider.invType;
920 auto item = provider.buildVoteItem();
921 auto itemid = provider.getVoteItemId(item);
928 std::set<NodeId> avanodeIds;
929 auto avanodes = ConnectNodes();
930 for (
auto avanode : avanodes) {
932 avanodeIds.insert(avanode->GetId());
935 auto getSelectedAvanodeId = [&]() {
936 NodeId avanodeid = getSuitableNodeToQuery();
937 BOOST_CHECK(avanodeIds.find(avanodeid) != avanodeIds.end());
942 NodeId avanodeid = getSelectedAvanodeId();
946 auto invs = getInvsForNextPoll();
951 std::set<NodeId> unselectedNodeids = avanodeIds;
952 unselectedNodeids.erase(avanodeid);
953 const size_t remainingNodeIds = unselectedNodeids.size();
955 uint64_t round = getRound();
956 for (
size_t i = 0; i < remainingNodeIds; i++) {
961 NodeId nodeid = getSuitableNodeToQuery();
962 BOOST_CHECK(unselectedNodeids.find(nodeid) != avanodeIds.end());
963 unselectedNodeids.erase(nodeid);
973 std::vector<avalanche::VoteItemUpdate> updates;
974 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
981 auto checkRegisterVotesError = [&](
NodeId nodeid,
983 const std::string &expectedError) {
991 checkRegisterVotesError(avanodeid, next(resp),
"unexpected-ava-response");
1000 resp = {round, 0, {
Vote(0, itemid),
Vote(0, itemid)}};
1002 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
1006 resp = {getRound(), 0, {}};
1008 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
1012 resp = {getRound(), 0, {
Vote()}};
1014 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1019 resp = {getRound(), 0, {
Vote(0, itemid)}};
1021 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1025 invs = getInvsForNextPoll();
1029 uint64_t queryRound = getRound();
1032 resp = {queryRound + 1, 0, {
Vote()}};
1033 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1035 resp = {queryRound - 1, 0, {
Vote()}};
1036 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1040 resp = {queryRound, 0, {
Vote(0, itemid)}};
1041 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1044 resp = {queryRound, 0, {
Vote(0, itemid)}};
1045 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1050 const auto item2 = provider.buildVoteItem();
1053 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1054 resp = {getRound(), 0, {votes[1], votes[0]}};
1056 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1060 resp = {getRound(), 0, votes};
1062 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1069 const uint32_t invType = provider.invType;
1071 auto itemA = provider.buildVoteItem();
1072 auto itemB = provider.buildVoteItem();
1074 auto avanodes = ConnectNodes();
1075 int nextNodeIndex = 0;
1078 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1084 auto invs = getInvsForNextPoll();
1086 for (
size_t i = 0; i < invs.size(); i++) {
1092 provider.invalidateItem(itemB);
1094 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1095 std::vector<avalanche::VoteItemUpdate> updates;
1098 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1099 goodResp, updates));
1103 invs = getInvsForNextPoll();
1106 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1109 Response badResp{getRound(), 0, votes};
1113 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1114 badResp, updates, error));
1118 votes = provider.buildVotesForItems(1, {itemA});
1119 auto registerNewVote = [&]() {
1120 Response resp = {getRound(), 0, votes};
1122 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1123 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1125 for (
size_t i = 0; i < 4000; i++) {
1127 if (updates.size() > 0 &&
1128 updates[0].getStatus() == VoteStatus::Invalid) {
1134 invs = getInvsForNextPoll();
1138 badResp =
Response(getRound(), 0, votes);
1141 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1142 badResp, updates, error));
1146BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1151 auto queryTimeDuration = std::chrono::milliseconds(10);
1152 setArg(
"-avatimeout",
ToString(queryTimeDuration.count()));
1154 setArg(
"-avalanchestakingpreconsensus",
"0");
1156 m_node.validation_signals->SyncWithValidationInterfaceQueue();
1158 m_node.avalanche = Processor::MakeProcessor(
1162 const auto item = provider.buildVoteItem();
1163 const auto itemid = provider.getVoteItemId(item);
1173 for (
int i = 0; i < 10; i++) {
1175 avanodeid = getSuitableNodeToQuery();
1177 auto start = Now<SteadyMilliseconds>();
1181 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1184 std::vector<avalanche::VoteItemUpdate> updates;
1185 bool ret = registerVotes(avanodeid, next(resp), updates);
1186 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1197 avanodeid = getSuitableNodeToQuery();
1201 std::this_thread::sleep_for(queryTimeDuration);
1203 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1209 const uint32_t invType = provider.invType;
1212 auto proof = GetProof();
1216 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1217 for (
auto &n : nodes) {
1223 const auto item = provider.buildVoteItem();
1224 const auto itemid = provider.getVoteItemId(item);
1228 std::map<NodeId, uint64_t> node_round_map;
1230 NodeId nodeid = getSuitableNodeToQuery();
1231 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1232 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1233 auto invs = getInvsForNextPoll();
1241 auto suitablenodeid = getSuitableNodeToQuery();
1243 auto invs = getInvsForNextPoll();
1249 auto it = node_round_map.begin();
1251 std::vector<avalanche::VoteItemUpdate> updates;
1252 BOOST_CHECK(registerVotes(it->first, resp, updates));
1253 node_round_map.erase(it);
1255 invs = getInvsForNextPoll();
1264 constexpr size_t numItems = 3;
1265 std::vector<CInv> itemInvs;
1266 itemInvs.reserve(numItems);
1267 for (
size_t i = 0; i < numItems; i++) {
1268 const auto item = provider.buildVoteItem();
1270 itemInvs.emplace_back(provider.invType, provider.getVoteItemId(item));
1273 auto contains = [](
const std::vector<CInv> &invs,
const CInv &target) {
1274 return std::find_if(invs.begin(), invs.end(), [&](
const CInv &inv) {
1275 return inv.type == target.type && inv.hash == target.hash;
1281 auto invs = getInvsForNextPoll(
true);
1288 clearInflightRequests(
1289 {{itemInvs[0], 1}, {itemInvs[1], 2}, {itemInvs[2], 3}});
1295 auto remaining = getInvsForNextPoll();
1304 auto remaining = getInvsForNextPoll();
1324 clearInflightRequests({});
1331 const uint32_t invType = provider.invType;
1333 auto proof = GetProof();
1340 std::vector<CNode *> nodes;
1341 nodes.reserve(numNodes);
1342 for (
size_t i = 0; i < numNodes; i++) {
1348 const auto item = provider.buildVoteItem();
1349 const auto itemid = provider.getVoteItemId(item);
1353 for (
CNode *n : nodes) {
1354 n->fDisconnect =
true;
1360 auto invs = getInvsForNextPoll();
1368 invs = getInvsForNextPoll();
1375 std::vector<VoteItemUpdate> updates;
1377 CBlock block = CreateAndProcessBlock({}, CScript());
1383 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1387 auto avanodes = ConnectNodes();
1396 uint64_t round = getRound();
1400 for (
size_t i = 0; i < avanodes.size(); i++) {
1402 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1406 const NodeId firstNodeId = getSuitableNodeToQuery();
1407 std::map<NodeId, uint64_t> node_round_map;
1409 for (
size_t i = 0; i < avanodes.size(); i++) {
1410 NodeId nodeid = getSuitableNodeToQuery();
1411 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1412 node_round_map[nodeid] = getRound();
1418 auto confidence =
m_node.avalanche->getConfidence(pindex);
1419 BOOST_REQUIRE(confidence > 0);
1421 for (
auto &[nodeid, r] : node_round_map) {
1422 if (nodeid == firstNodeId) {
1429 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1434 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1441 CBlock block = CreateAndProcessBlock({}, CScript());
1447 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1454 std::chrono::steady_clock::time_point start,
stop;
1464 auto avanodes = ConnectNodes();
1467 NodeId nodeid = getSuitableNodeToQuery();
1468 BOOST_CHECK_NE(nodeid,
NO_NODE);
1471 uint64_t queryRound = getRound();
1475 for (
int i = 0; i < 60 * 1000; i++) {
1479 if (getRound() == queryRound + avanodes.size()) {
1488 uint64_t responseRound = getRound();
1489 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1491 std::vector<VoteItemUpdate> updates;
1493 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1496 for (
int i = 0; i < 10000; i++) {
1499 if (getRound() != responseRound) {
1500 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1519 schedulerThread.join();
1524 std::chrono::steady_clock::time_point start,
stop;
1526 std::thread schedulerThread;
1535 m_node.validation_signals->SyncWithValidationInterfaceQueue();
1537 m_node.avalanche.reset();
1544 schedulerThread.join();
1551 auto addProofToReconcile = [&](uint32_t proofScore) {
1561 auto proof = addProofToReconcile(++score);
1563 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1572 for (
size_t i = 0; i < 10; i++) {
1573 auto proof = addProofToReconcile(++score);
1575 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1580 lastProofId = proof->
getId();
1583 for (
size_t i = 0; i < 10; i++) {
1584 auto proof = addProofToReconcile(--score);
1586 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1595 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1597 for (
auto &inv : invs) {
1598 BOOST_CHECK_NE(inv.hash, proof->
getId());
1604 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1605 setArg(
"-avalancheconflictingproofcooldown",
"0");
1619 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1620 coins.
AddCoin(conflictingOutpoint,
1623 coins.
AddCoin(immatureOutpoint,
1628 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1629 uint32_t height = 10) {
1636 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1637 auto validProof = buildProof(conflictingOutpoint, 2);
1638 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1689 int minStake = 400'000'000;
1690 setArg(
"-avaminquorumstake",
ToString(minStake));
1691 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1695 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1703 setArg(
"-avaproof", localProof->ToHex());
1705 m_node.validation_signals->SyncWithValidationInterfaceQueue();
1708 m_node.avalanche = Processor::MakeProcessor(
1715 localProof->getId());
1719 AvalancheTest::getMinQuorumConnectedScoreRatio(*
m_node.avalanche), 0.5);
1741 for (
NodeId id = 0;
id < 8;
id++) {
1760 const int64_t tipTime =
1764 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1765 const int height = 100;
1766 const bool isCoinbase =
false;
1773 height, isCoinbase),
1778 auto proof2 = pb.
build();
1808 m_node.avalanche->withPeerManager(
1820 auto spendProofUtxo = [&](
ProofRef proof) {
1833 for (int64_t i = 0; i < 6; i++) {
1835 CreateAndProcessBlock({}, CScript());
1839 ->GetMedianTimePast(),
1840 proof2->getExpirationTime());
1851 spendProofUtxo(proof1);
1858 spendProofUtxo(
m_node.avalanche->getLocalProof());
1870 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1873 {
"",
"",
"",
false},
1874 {
"-1",
"-1",
"-1",
false},
1877 {
"-1",
"0",
"0",
false},
1878 {
"-0.01",
"0",
"0",
false},
1879 {
"21000000000000.01",
"0",
"0",
false},
1882 {
"0",
"-1",
"0",
false},
1883 {
"0",
"1.1",
"0",
false},
1886 {
"0",
"0",
"-1",
false},
1889 {
"0",
"0",
"0",
true},
1890 {
"0.00",
"0",
"0",
true},
1891 {
"0.01",
"0",
"0",
true},
1892 {
"1",
"0.1",
"0",
true},
1893 {
"10",
"0.5",
"0",
true},
1894 {
"10",
"1",
"0",
true},
1895 {
"21000000000000.00",
"0",
"0",
true},
1896 {
"0",
"0",
"1",
true},
1897 {
"0",
"0",
"100",
true},
1902 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1904 setArg(
"-avaminquorumstake", stake);
1905 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1906 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1909 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1929 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1930 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1933 auto processor = Processor::MakeProcessor(
1937 auto addNode = [&](
NodeId nodeid) {
1951 for (
NodeId id = 100;
id < 108;
id++) {
1956 minAvaproofsMessages <= 0);
1958 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1961 processor->avaproofsSent(i);
1965 processor->avaproofsSent(i);
1971 addNode(minAvaproofsMessages);
1972 processor->avaproofsSent(minAvaproofsMessages);
1976 AvalancheTest::clearavaproofsNodeCounter(*processor);
1980 checkMinAvaproofsMessages(0);
1981 checkMinAvaproofsMessages(1);
1982 checkMinAvaproofsMessages(10);
1983 checkMinAvaproofsMessages(100);
1988 setArg(
"-avastalevotethreshold",
1990 setArg(
"-avastalevotefactor",
"2");
1992 setArg(
"-avalanchestakingpreconsensus",
"0");
1994 const std::vector<std::tuple<int, int>> testCases = {
2000 m_node.validation_signals->SyncWithValidationInterfaceQueue();
2002 m_node.avalanche = Processor::MakeProcessor(
2011 const uint32_t invType = provider.invType;
2013 const auto item = provider.buildVoteItem();
2014 const auto itemid = provider.getVoteItemId(item);
2017 auto avanodes = ConnectNodes();
2018 int nextNodeIndex = 0;
2020 std::vector<avalanche::VoteItemUpdate> updates;
2021 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
2024 auto invs = getInvsForNextPoll();
2031 auto registerNewVote = [&](
const Response &resp) {
2033 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
2034 BOOST_CHECK(registerVotes(nodeid, resp, updates));
2038 for (
int i = 0; i < numYesVotes; i++) {
2040 registerNewVote(next(resp));
2043 i >= 6 ? i - 5 : 0);
2048 for (
int i = 0; i < numNeutralVotes; i++) {
2050 registerNewVote(next(resp));
2055 invs = getInvsForNextPoll();
2062 registerNewVote(next(resp));
2064 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
2065 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
2068 invs = getInvsForNextPoll();
2074 BlockProvider provider(
this);
2078 std::vector<CBlockIndex *> blockIndexes;
2082 blockIndexes.push_back(pindex);
2085 auto invs = getInvsForNextPoll();
2099 std::vector<Vote> votes;
2102 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
2103 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
2106 auto avanodes = ConnectNodes();
2107 int nextNodeIndex = 0;
2109 std::vector<avalanche::VoteItemUpdate> updates;
2110 auto registerNewVote = [&]() {
2111 Response resp = {getRound(), 0, votes};
2113 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
2114 BOOST_CHECK(registerVotes(nodeid, resp, updates));
2120 bool eleventhBlockFinalized =
false;
2121 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
2124 for (
auto &update : updates) {
2125 if (update.getStatus() == VoteStatus::Finalized &&
2126 provider.fromAnyVoteItem(update.getVoteItem())
2127 ->GetBlockHash() == eleventhBlockHash) {
2128 eleventhBlockFinalized =
true;
2139 clearInvsNotWorthPolling();
2140 invs = getInvsForNextPoll();
2142 for (
size_t i = 0; i < 10; i++) {
2157 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2159 activeChainstate.InvalidateBlock(state, tip);
2162 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2165 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2173 activeChainstate.ResetBlockFailureFlags(tip);
2175 activeChainstate.ActivateBestChain(state);
2179 clearInvsNotWorthPolling();
2180 invs = getInvsForNextPoll();
2187 for (
auto &inv : invs) {
2188 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2191 bool tipFinalized =
false;
2192 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2195 for (
auto &update : updates) {
2196 if (update.getStatus() == VoteStatus::Finalized &&
2197 provider.fromAnyVoteItem(update.getVoteItem())
2198 ->GetBlockHash() == tiphash) {
2199 tipFinalized =
true;
2208 clearInvsNotWorthPolling();
2209 invs = getInvsForNextPoll();
2217 BlockHash alttiphash = alttip->GetBlockHash();
2218 votes = {{1, alttiphash}};
2220 bool alttipInvalidated =
false;
2221 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2224 for (
auto &update : updates) {
2225 if (update.getStatus() == VoteStatus::Invalid &&
2226 provider.fromAnyVoteItem(update.getVoteItem())
2227 ->GetBlockHash() == alttiphash) {
2228 alttipInvalidated =
true;
2233 invs = getInvsForNextPoll();
2244 const int numberElementsEachType = 100;
2247 std::vector<ProofRef> proofs;
2248 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2252 proofs.emplace_back(std::move(proof));
2254 Shuffle(proofs.begin(), proofs.end(), rng);
2256 std::vector<CBlockIndex> indexes;
2257 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2260 indexes.emplace_back(std::move(index));
2262 Shuffle(indexes.begin(), indexes.end(), rng);
2264 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2265 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2271 for (
size_t i = 0; i < numberElementsEachType; i++) {
2273 const size_t firstType = rng.
randrange(numTypes);
2275 for (
size_t j = 0; j < numTypes; j++) {
2276 switch ((firstType + j) % numTypes) {
2279 writeView->insert(std::make_pair(
2280 std::get<0>(allItems)[i],
VoteRecord(
true)));
2284 writeView->insert(std::make_pair(
2285 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2296 auto readView = voteMap.getReadView();
2297 auto it = readView.begin();
2300 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2301 for (
size_t i = 0; i < numberElementsEachType; i++) {
2302 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2304 uint32_t currentScore =
2305 std::get<const ProofRef>(it->first)->getScore();
2306 BOOST_CHECK_LT(currentScore, lastScore);
2307 lastScore = currentScore;
2315 for (
size_t i = 0; i < numberElementsEachType; i++) {
2316 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2319 std::get<const CBlockIndex *>(it->first)->nChainWork;
2321 lastWork = currentWork;
2334 const auto block = std::make_shared<const CBlock>(
2335 this->CreateBlock({}, CScript(), chainstate));
2362 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
2372 auto now = GetTime<std::chrono::seconds>();
2378 std::vector<CScript> winners;
2381 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2386 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2391 prevBlock.
nTime = now.count();
2396 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2399 size_t numProofs = 10;
2400 std::vector<ProofRef> proofs;
2401 proofs.reserve(numProofs);
2402 for (
size_t i = 0; i < numProofs; i++) {
2406 auto proof = GetProof(payoutScript);
2413 return pm.setFinalized(peer.peerid);
2417 proofs.emplace_back(std::move(proof));
2425 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2428 auto winnerExists = [&](
const CScript &expectedWinner) {
2429 const std::string winnerString =
FormatScript(expectedWinner);
2431 for (
const ProofRef &proof : proofs) {
2442 prevBlock.
nTime = now.count();
2447 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2453 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2459 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2463 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2468 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2472 m_node.avalanche->cleanupStakingRewards(101);
2476 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2480 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2486 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2490 m_node.avalanche->cleanupStakingRewards(200);
2494 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2496 !
m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2508 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2514 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2522 auto localProof = buildProof(outpoint, 1, 100);
2525 setArg(
"-avaproof", localProof->ToHex());
2526 setArg(
"-avalancheconflictingproofcooldown",
"0");
2527 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2528 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2530 m_node.validation_signals->SyncWithValidationInterfaceQueue();
2533 m_node.avalanche = Processor::MakeProcessor(
2538 localProof->getId());
2540 auto checkLocalProofState = [&](
const bool boundToPeer,
2545 return pm.isBoundToPeer(localProof->getId());
2548 BOOST_CHECK_MESSAGE(
2549 m_node.avalanche->getLocalProofRegistrationState().GetResult() ==
2551 m_node.avalanche->getLocalProofRegistrationState().ToString());
2558 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2562 AvalancheTest::setLocalProofShareable(*
m_node.avalanche,
true);
2564 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2565 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2569 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2570 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2574 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2578 auto conflictingProof = buildProof(outpoint, 2, 100);
2584 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2585 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2589 setArg(
"-avalancheconflictingproofcooldown",
"0");
2590 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2610 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2617 auto proof = buildProof(outpoint, 1);
2636 AvalancheTest::addProofToRecentfinalized(*
m_node.avalanche, proof->
getId());
2643 return peer.hasFinalized;
2650 auto betterProof = buildProof(outpoint, 2);
2672 m_node.validation_signals->SyncWithValidationInterfaceQueue();
2674 m_node.avalanche = Processor::MakeProcessor(
2680 auto now = GetTime<std::chrono::seconds>();
2683 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
true);
2691 const ProofId proofid1 = proof1->getId();
2696 const ProofId proofid2 = proof2->getId();
2707 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2709 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2715 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2720 for (
NodeId n = 0; n < 8; n++) {
2725 return pm.setFinalized(peer.peerid);
2734 CBlock block = CreateAndProcessBlock({}, CScript());
2737 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2738 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2744 std::vector<CScript> winners;
2748 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2753 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2757 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2759 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2765 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2771 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2779 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2782 m_node.avalanche->getStakeContenderStatus(contender1_block1), -1);
2784 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2787 m_node.avalanche->getStakeContenderStatus(contender2_block1), -1);
2789 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2792 m_node.avalanche->setStakingRewardWinners(
2793 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2798 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2801 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2804 m_node.avalanche->withPeerManager(
2810 const ProofId proofid3 = proof3->getId();
2813 for (
NodeId n = 0; n < 8; n++) {
2819 block = CreateAndProcessBlock({}, CScript());
2822 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2823 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2827 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2831 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2833 m_node.avalanche->getStakeContenderStatus(contender2_block2), -1);
2840 m_node.avalanche->getStakeContenderStatus(contender1_block3), -1);
2844 m_node.avalanche->getStakeContenderStatus(contender2_block3), -1);
2847 m_node.avalanche->withPeerManager(
2851 size_t numProofs = 8;
2852 std::vector<ProofRef> proofs;
2853 proofs.reserve(numProofs);
2854 for (
size_t i = 0; i < numProofs; i++) {
2863 return pm.setFinalized(peer.peerid);
2866 proofs.emplace_back(std::move(proof));
2871 const ProofId proofid = proofs[0]->getId();
2872 for (
NodeId n = 0; n < 8; n++) {
2882 std::vector<CScript> winners;
2883 for (
int attempt = 0; attempt < 10; attempt++) {
2885 block = CreateAndProcessBlock({}, CScript());
2888 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2889 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2895 chaintip->GetBlockHash(), winners));
2896 if (winners.size() == 8) {
2904 size_t numAccepted = 0;
2905 for (
const auto &proof : proofs) {
2909 if (
m_node.avalanche->getStakeContenderStatus(contender) == 0) {
2911 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2919 block = CreateAndProcessBlock({}, CScript());
2922 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2927 m_node.avalanche->withPeerManager(
2929 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2938 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2939 bestproof->getPayoutScript()) == winners.end());
2946 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2957 block = CreateAndProcessBlock({}, CScript());
2960 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2961 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2962 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
2969 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2983 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2984 bestproof->getPayoutScript()) == winners.end());
2991 m_node.avalanche->getStakeContenderStatus(bestcontender), 4);
3002 auto now = GetTime<std::chrono::seconds>();
3006 auto localWinnerProof =
3008 ProofId localWinnerProofId = localWinnerProof->getId();
3010 localWinnerProof->getId());
3016 chaintip->
nTime = (now + registration_delay).
count();
3022 for (
NodeId n = 0; n < 8; n++) {
3023 pm.
addNode(n, localWinnerProofId,
3027 return pm.setFinalized(peer.peerid);
3032 now += registration_delay;
3039 std::vector<ProofRef> acceptedContenderProofs;
3040 acceptedContenderProofs.push_back(localWinnerProof);
3047 for (
size_t numContenders = 2;
3051 m_node.avalanche->withPeerManager(
3057 if (rank <= bestRank) {
3059 acceptedContenderProofs.push_back(proof);
3060 const size_t numAccepted =
3062 acceptedContenderProofs.size());
3063 std::sort(acceptedContenderProofs.begin(),
3064 acceptedContenderProofs.begin() + numAccepted,
3066 const ProofId leftProofId = left->getId();
3067 const ProofId rightProofId = right->getId();
3068 const StakeContenderId leftContenderId(chaintipHash,
3070 const StakeContenderId rightContenderId(chaintipHash,
3072 return RewardRankComparator()(
3074 leftContenderId.ComputeProofRewardRank(
3075 MIN_VALID_PROOF_SCORE),
3076 leftProofId, rightContenderId,
3077 rightContenderId.ComputeProofRewardRank(
3078 MIN_VALID_PROOF_SCORE),
3083 std::vector<StakeContenderId> pollableContenders;
3084 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
3085 *
m_node.avalanche, chaintip, pollableContenders));
3087 pollableContenders.size(),
3092 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
3096 chaintipHash, acceptedContenderProofs[i]->getId());
3098 std::find(pollableContenders.begin(), pollableContenders.end(),
3099 acceptedContenderId) != pollableContenders.end());
3101 m_node.avalanche->getStakeContenderStatus(acceptedContenderId),
3106 std::set<StakeContenderId> unacceptedContenderIds(
3107 pollableContenders.begin(), pollableContenders.end());
3108 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
3110 chaintipHash, acceptedContenderProof->getId());
3111 unacceptedContenderIds.erase(acceptedContenderId);
3114 for (
auto cid : unacceptedContenderIds) {
3121 m_node.avalanche->getStakeContenderStatus(localWinnerContenderId),
3126BOOST_AUTO_TEST_SUITE_END()
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
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.
Inv(ventory) message data.
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
void clearInflightRequests(const std::vector< CInv > &invs) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Decrement VoteRecord::inflight for each inventory.
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.
A BlockHash is a unqiue identifier for a block.
static const Currency & get()
A TxId is the identifier of a transaction.
static constexpr auto DANGLING_TIMEOUT
Consider dropping the peer if no node is attached after this timeout expired.
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.
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.