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");
1021 invs = getInvsForNextPoll();
1024 item = provider.buildVoteItem();
1025 itemid = provider.getVoteItemId(item);
1028 invs = getInvsForNextPoll();
1032 uint64_t queryRound = getRound();
1035 resp = {queryRound + 1, 0, {
Vote()}};
1036 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1038 resp = {queryRound - 1, 0, {
Vote()}};
1039 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1043 resp = {queryRound, 0, {
Vote(0, itemid)}};
1044 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1047 resp = {queryRound, 0, {
Vote(0, itemid)}};
1048 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1053 const auto item2 = provider.buildVoteItem();
1056 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1057 resp = {getRound(), 0, {votes[1], votes[0]}};
1059 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1063 resp = {getRound(), 0, votes};
1065 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1072 const uint32_t invType = provider.invType;
1074 auto itemA = provider.buildVoteItem();
1075 auto itemB = provider.buildVoteItem();
1077 auto avanodes = ConnectNodes();
1078 int nextNodeIndex = 0;
1081 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1087 auto invs = getInvsForNextPoll();
1089 for (
size_t i = 0; i < invs.size(); i++) {
1095 provider.invalidateItem(itemB);
1097 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1098 std::vector<avalanche::VoteItemUpdate> updates;
1101 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1102 goodResp, updates));
1106 invs = getInvsForNextPoll();
1109 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1112 Response badResp{getRound(), 0, votes};
1116 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1117 badResp, updates, error));
1121 votes = provider.buildVotesForItems(1, {itemA});
1122 auto registerNewVote = [&]() {
1123 Response resp = {getRound(), 0, votes};
1125 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1126 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1128 for (
size_t i = 0; i < 4000; i++) {
1130 if (updates.size() > 0 &&
1131 updates[0].getStatus() == VoteStatus::Invalid) {
1137 invs = getInvsForNextPoll();
1141 badResp =
Response(getRound(), 0, votes);
1144 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1145 badResp, updates, error));
1149BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1154 auto queryTimeDuration = std::chrono::milliseconds(10);
1155 setArg(
"-avatimeout",
ToString(queryTimeDuration.count()));
1157 setArg(
"-avalanchestakingpreconsensus",
"0");
1161 m_node.avalanche = Processor::MakeProcessor(
1165 const auto item = provider.buildVoteItem();
1166 const auto itemid = provider.getVoteItemId(item);
1176 for (
int i = 0; i < 10; i++) {
1178 avanodeid = getSuitableNodeToQuery();
1180 auto start = Now<SteadyMilliseconds>();
1184 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1187 std::vector<avalanche::VoteItemUpdate> updates;
1188 bool ret = registerVotes(avanodeid, next(resp), updates);
1189 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1200 avanodeid = getSuitableNodeToQuery();
1204 std::this_thread::sleep_for(queryTimeDuration);
1206 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1212 const uint32_t invType = provider.invType;
1215 auto proof = GetProof();
1219 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1220 for (
auto &n : nodes) {
1226 const auto item = provider.buildVoteItem();
1227 const auto itemid = provider.getVoteItemId(item);
1231 std::map<NodeId, uint64_t> node_round_map;
1233 NodeId nodeid = getSuitableNodeToQuery();
1234 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1235 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1236 auto invs = getInvsForNextPoll();
1244 auto suitablenodeid = getSuitableNodeToQuery();
1246 auto invs = getInvsForNextPoll();
1252 auto it = node_round_map.begin();
1254 std::vector<avalanche::VoteItemUpdate> updates;
1255 BOOST_CHECK(registerVotes(it->first, resp, updates));
1256 node_round_map.erase(it);
1258 invs = getInvsForNextPoll();
1267 constexpr size_t numItems = 3;
1268 std::vector<CInv> itemInvs;
1269 itemInvs.reserve(numItems);
1270 for (
size_t i = 0; i < numItems; i++) {
1271 const auto item = provider.buildVoteItem();
1273 itemInvs.emplace_back(provider.invType, provider.getVoteItemId(item));
1276 auto contains = [](
const std::vector<CInv> &invs,
const CInv &target) {
1277 return std::find_if(invs.begin(), invs.end(), [&](
const CInv &inv) {
1278 return inv.type == target.type && inv.hash == target.hash;
1284 auto invs = getInvsForNextPoll(
true);
1291 clearInflightRequests(
1292 {{itemInvs[0], 1}, {itemInvs[1], 2}, {itemInvs[2], 3}});
1298 auto remaining = getInvsForNextPoll();
1307 auto remaining = getInvsForNextPoll();
1327 clearInflightRequests({});
1334 const uint32_t invType = provider.invType;
1336 auto proof = GetProof();
1343 std::vector<CNode *> nodes;
1344 nodes.reserve(numNodes);
1345 for (
size_t i = 0; i < numNodes; i++) {
1351 const auto item = provider.buildVoteItem();
1352 const auto itemid = provider.getVoteItemId(item);
1356 for (
CNode *n : nodes) {
1357 n->fDisconnect =
true;
1363 auto invs = getInvsForNextPoll();
1371 invs = getInvsForNextPoll();
1378 std::vector<VoteItemUpdate> updates;
1380 CBlock block = CreateAndProcessBlock({}, CScript());
1386 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1390 auto avanodes = ConnectNodes();
1399 uint64_t round = getRound();
1403 for (
size_t i = 0; i < avanodes.size(); i++) {
1405 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1409 const NodeId firstNodeId = getSuitableNodeToQuery();
1410 std::map<NodeId, uint64_t> node_round_map;
1412 for (
size_t i = 0; i < avanodes.size(); i++) {
1413 NodeId nodeid = getSuitableNodeToQuery();
1414 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1415 node_round_map[nodeid] = getRound();
1421 auto confidence =
m_node.avalanche->getConfidence(pindex);
1422 BOOST_REQUIRE(confidence > 0);
1424 for (
auto &[nodeid, r] : node_round_map) {
1425 if (nodeid == firstNodeId) {
1432 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1437 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1444 CBlock block = CreateAndProcessBlock({}, CScript());
1450 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1457 std::chrono::steady_clock::time_point start,
stop;
1467 auto avanodes = ConnectNodes();
1470 NodeId nodeid = getSuitableNodeToQuery();
1471 BOOST_CHECK_NE(nodeid,
NO_NODE);
1474 uint64_t queryRound = getRound();
1478 for (
int i = 0; i < 60 * 1000; i++) {
1482 if (getRound() == queryRound + avanodes.size()) {
1491 uint64_t responseRound = getRound();
1492 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1494 std::vector<VoteItemUpdate> updates;
1496 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1499 for (
int i = 0; i < 10000; i++) {
1502 if (getRound() != responseRound) {
1503 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1522 schedulerThread.join();
1527 std::chrono::steady_clock::time_point start,
stop;
1529 std::thread schedulerThread;
1540 m_node.avalanche.reset();
1547 schedulerThread.join();
1554 auto addProofToReconcile = [&](uint32_t proofScore) {
1564 auto proof = addProofToReconcile(++score);
1566 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1575 for (
size_t i = 0; i < 10; i++) {
1576 auto proof = addProofToReconcile(++score);
1578 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1583 lastProofId = proof->
getId();
1586 for (
size_t i = 0; i < 10; i++) {
1587 auto proof = addProofToReconcile(--score);
1589 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1598 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1600 for (
auto &inv : invs) {
1601 BOOST_CHECK_NE(inv.hash, proof->
getId());
1607 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1608 setArg(
"-avalancheconflictingproofcooldown",
"0");
1622 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1623 coins.
AddCoin(conflictingOutpoint,
1626 coins.
AddCoin(immatureOutpoint,
1631 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1632 uint32_t height = 10) {
1639 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1640 auto validProof = buildProof(conflictingOutpoint, 2);
1641 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1692 int minStake = 400'000'000;
1693 setArg(
"-avaminquorumstake",
ToString(minStake));
1694 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1698 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1706 setArg(
"-avaproof", localProof->ToHex());
1711 m_node.avalanche = Processor::MakeProcessor(
1718 localProof->getId());
1722 AvalancheTest::getMinQuorumConnectedScoreRatio(*
m_node.avalanche), 0.5);
1744 for (
NodeId id = 0;
id < 8;
id++) {
1763 const int64_t tipTime =
1767 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1768 const int height = 100;
1769 const bool isCoinbase =
false;
1776 height, isCoinbase),
1781 auto proof2 = pb.
build();
1811 m_node.avalanche->withPeerManager(
1823 auto spendProofUtxo = [&](
ProofRef proof) {
1836 for (int64_t i = 0; i < 6; i++) {
1838 CreateAndProcessBlock({}, CScript());
1842 ->GetMedianTimePast(),
1843 proof2->getExpirationTime());
1854 spendProofUtxo(proof1);
1861 spendProofUtxo(
m_node.avalanche->getLocalProof());
1873 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1876 {
"",
"",
"",
false},
1877 {
"-1",
"-1",
"-1",
false},
1880 {
"-1",
"0",
"0",
false},
1881 {
"-0.01",
"0",
"0",
false},
1882 {
"21000000000000.01",
"0",
"0",
false},
1885 {
"0",
"-1",
"0",
false},
1886 {
"0",
"1.1",
"0",
false},
1889 {
"0",
"0",
"-1",
false},
1892 {
"0",
"0",
"0",
true},
1893 {
"0.00",
"0",
"0",
true},
1894 {
"0.01",
"0",
"0",
true},
1895 {
"1",
"0.1",
"0",
true},
1896 {
"10",
"0.5",
"0",
true},
1897 {
"10",
"1",
"0",
true},
1898 {
"21000000000000.00",
"0",
"0",
true},
1899 {
"0",
"0",
"1",
true},
1900 {
"0",
"0",
"100",
true},
1905 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1907 setArg(
"-avaminquorumstake", stake);
1908 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1909 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1912 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1932 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1933 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1936 auto processor = Processor::MakeProcessor(
1940 auto addNode = [&](
NodeId nodeid) {
1954 for (
NodeId id = 100;
id < 108;
id++) {
1959 minAvaproofsMessages <= 0);
1961 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1964 processor->avaproofsSent(i);
1968 processor->avaproofsSent(i);
1974 addNode(minAvaproofsMessages);
1975 processor->avaproofsSent(minAvaproofsMessages);
1979 AvalancheTest::clearavaproofsNodeCounter(*processor);
1983 checkMinAvaproofsMessages(0);
1984 checkMinAvaproofsMessages(1);
1985 checkMinAvaproofsMessages(10);
1986 checkMinAvaproofsMessages(100);
1991 setArg(
"-avastalevotethreshold",
1993 setArg(
"-avastalevotefactor",
"2");
1995 setArg(
"-avalanchestakingpreconsensus",
"0");
1997 const std::vector<std::tuple<int, int>> testCases = {
2005 m_node.avalanche = Processor::MakeProcessor(
2014 const uint32_t invType = provider.invType;
2016 const auto item = provider.buildVoteItem();
2017 const auto itemid = provider.getVoteItemId(item);
2020 auto avanodes = ConnectNodes();
2021 int nextNodeIndex = 0;
2023 std::vector<avalanche::VoteItemUpdate> updates;
2024 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
2027 auto invs = getInvsForNextPoll();
2034 auto registerNewVote = [&](
const Response &resp) {
2036 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
2037 BOOST_CHECK(registerVotes(nodeid, resp, updates));
2041 for (
int i = 0; i < numYesVotes; i++) {
2043 registerNewVote(next(resp));
2046 i >= 6 ? i - 5 : 0);
2051 for (
int i = 0; i < numNeutralVotes; i++) {
2053 registerNewVote(next(resp));
2058 invs = getInvsForNextPoll();
2065 registerNewVote(next(resp));
2067 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
2068 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
2071 invs = getInvsForNextPoll();
2077 BlockProvider provider(
this);
2081 std::vector<CBlockIndex *> blockIndexes;
2085 blockIndexes.push_back(pindex);
2088 auto invs = getInvsForNextPoll();
2102 std::vector<Vote> votes;
2105 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
2106 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
2109 auto avanodes = ConnectNodes();
2110 int nextNodeIndex = 0;
2112 std::vector<avalanche::VoteItemUpdate> updates;
2113 auto registerNewVote = [&]() {
2114 Response resp = {getRound(), 0, votes};
2116 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
2117 BOOST_CHECK(registerVotes(nodeid, resp, updates));
2123 bool eleventhBlockFinalized =
false;
2124 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
2127 for (
auto &update : updates) {
2128 if (update.getStatus() == VoteStatus::Finalized &&
2129 provider.fromAnyVoteItem(update.getVoteItem())
2130 ->GetBlockHash() == eleventhBlockHash) {
2131 eleventhBlockFinalized =
true;
2142 clearInvsNotWorthPolling();
2143 invs = getInvsForNextPoll();
2145 for (
size_t i = 0; i < 10; i++) {
2160 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2162 activeChainstate.InvalidateBlock(state, tip);
2165 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2168 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2176 activeChainstate.ResetBlockFailureFlags(tip);
2178 activeChainstate.ActivateBestChain(state);
2182 clearInvsNotWorthPolling();
2183 invs = getInvsForNextPoll();
2190 for (
auto &inv : invs) {
2191 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2194 bool tipFinalized =
false;
2195 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2198 for (
auto &update : updates) {
2199 if (update.getStatus() == VoteStatus::Finalized &&
2200 provider.fromAnyVoteItem(update.getVoteItem())
2201 ->GetBlockHash() == tiphash) {
2202 tipFinalized =
true;
2211 clearInvsNotWorthPolling();
2212 invs = getInvsForNextPoll();
2220 BlockHash alttiphash = alttip->GetBlockHash();
2221 votes = {{1, alttiphash}};
2223 bool alttipInvalidated =
false;
2224 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2227 for (
auto &update : updates) {
2228 if (update.getStatus() == VoteStatus::Invalid &&
2229 provider.fromAnyVoteItem(update.getVoteItem())
2230 ->GetBlockHash() == alttiphash) {
2231 alttipInvalidated =
true;
2236 invs = getInvsForNextPoll();
2247 const int numberElementsEachType = 100;
2250 std::vector<ProofRef> proofs;
2251 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2255 proofs.emplace_back(std::move(proof));
2257 Shuffle(proofs.begin(), proofs.end(), rng);
2259 std::vector<CBlockIndex> indexes;
2260 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2263 indexes.emplace_back(std::move(index));
2265 Shuffle(indexes.begin(), indexes.end(), rng);
2267 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2268 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2274 for (
size_t i = 0; i < numberElementsEachType; i++) {
2276 const size_t firstType = rng.
randrange(numTypes);
2278 for (
size_t j = 0; j < numTypes; j++) {
2279 switch ((firstType + j) % numTypes) {
2282 writeView->insert(std::make_pair(
2283 std::get<0>(allItems)[i],
VoteRecord(
true)));
2287 writeView->insert(std::make_pair(
2288 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2299 auto readView = voteMap.getReadView();
2300 auto it = readView.begin();
2303 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2304 for (
size_t i = 0; i < numberElementsEachType; i++) {
2305 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2307 uint32_t currentScore =
2308 std::get<const ProofRef>(it->first)->getScore();
2309 BOOST_CHECK_LT(currentScore, lastScore);
2310 lastScore = currentScore;
2318 for (
size_t i = 0; i < numberElementsEachType; i++) {
2319 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2322 std::get<const CBlockIndex *>(it->first)->nChainWork;
2324 lastWork = currentWork;
2337 const auto block = std::make_shared<const CBlock>(
2338 this->CreateBlock({}, CScript(), chainstate));
2365 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
2375 auto now = GetTime<std::chrono::seconds>();
2381 std::vector<CScript> winners;
2384 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2389 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2394 prevBlock.
nTime = now.count();
2399 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2402 size_t numProofs = 10;
2403 std::vector<ProofRef> proofs;
2404 proofs.reserve(numProofs);
2405 for (
size_t i = 0; i < numProofs; i++) {
2409 auto proof = GetProof(payoutScript);
2416 return pm.setFinalized(peer.peerid);
2420 proofs.emplace_back(std::move(proof));
2428 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2431 auto winnerExists = [&](
const CScript &expectedWinner) {
2432 const std::string winnerString =
FormatScript(expectedWinner);
2434 for (
const ProofRef &proof : proofs) {
2445 prevBlock.
nTime = now.count();
2450 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2456 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2462 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2466 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2471 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2475 m_node.avalanche->cleanupStakingRewards(101);
2479 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2483 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2489 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2493 m_node.avalanche->cleanupStakingRewards(200);
2497 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2499 !
m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2511 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2517 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2525 auto localProof = buildProof(outpoint, 1, 100);
2528 setArg(
"-avaproof", localProof->ToHex());
2529 setArg(
"-avalancheconflictingproofcooldown",
"0");
2530 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2531 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2536 m_node.avalanche = Processor::MakeProcessor(
2541 localProof->getId());
2543 auto checkLocalProofState = [&](
const bool boundToPeer,
2548 return pm.isBoundToPeer(localProof->getId());
2551 BOOST_CHECK_MESSAGE(
2552 m_node.avalanche->getLocalProofRegistrationState().GetResult() ==
2554 m_node.avalanche->getLocalProofRegistrationState().ToString());
2561 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2565 AvalancheTest::setLocalProofShareable(*
m_node.avalanche,
true);
2567 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2568 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2572 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2573 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2577 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2581 auto conflictingProof = buildProof(outpoint, 2, 100);
2587 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2588 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2592 setArg(
"-avalancheconflictingproofcooldown",
"0");
2593 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2613 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2620 auto proof = buildProof(outpoint, 1);
2639 AvalancheTest::addProofToRecentfinalized(*
m_node.avalanche, proof->
getId());
2646 return peer.hasFinalized;
2653 auto betterProof = buildProof(outpoint, 2);
2677 m_node.avalanche = Processor::MakeProcessor(
2683 auto now = GetTime<std::chrono::seconds>();
2686 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
true);
2694 const ProofId proofid1 = proof1->getId();
2699 const ProofId proofid2 = proof2->getId();
2710 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2712 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2718 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2723 for (
NodeId n = 0; n < 8; n++) {
2728 return pm.setFinalized(peer.peerid);
2737 CBlock block = CreateAndProcessBlock({}, CScript());
2740 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2741 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2747 std::vector<CScript> winners;
2751 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2756 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2760 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2762 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2768 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2774 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2782 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2785 m_node.avalanche->getStakeContenderStatus(contender1_block1), -1);
2787 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2790 m_node.avalanche->getStakeContenderStatus(contender2_block1), -1);
2792 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2795 m_node.avalanche->setStakingRewardWinners(
2796 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2801 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2804 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2807 m_node.avalanche->withPeerManager(
2813 const ProofId proofid3 = proof3->getId();
2816 for (
NodeId n = 0; n < 8; n++) {
2822 block = CreateAndProcessBlock({}, CScript());
2825 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2826 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2830 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2834 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2836 m_node.avalanche->getStakeContenderStatus(contender2_block2), -1);
2843 m_node.avalanche->getStakeContenderStatus(contender1_block3), -1);
2847 m_node.avalanche->getStakeContenderStatus(contender2_block3), -1);
2850 m_node.avalanche->withPeerManager(
2854 size_t numProofs = 8;
2855 std::vector<ProofRef> proofs;
2856 proofs.reserve(numProofs);
2857 for (
size_t i = 0; i < numProofs; i++) {
2866 return pm.setFinalized(peer.peerid);
2869 proofs.emplace_back(std::move(proof));
2874 const ProofId proofid = proofs[0]->getId();
2875 for (
NodeId n = 0; n < 8; n++) {
2885 std::vector<CScript> winners;
2886 for (
int attempt = 0; attempt < 10; attempt++) {
2888 block = CreateAndProcessBlock({}, CScript());
2891 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2892 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2898 chaintip->GetBlockHash(), winners));
2899 if (winners.size() == 8) {
2907 size_t numAccepted = 0;
2908 for (
const auto &proof : proofs) {
2912 if (
m_node.avalanche->getStakeContenderStatus(contender) == 0) {
2914 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2922 block = CreateAndProcessBlock({}, CScript());
2925 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2930 m_node.avalanche->withPeerManager(
2932 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2941 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2942 bestproof->getPayoutScript()) == winners.end());
2949 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2960 block = CreateAndProcessBlock({}, CScript());
2963 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2964 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2965 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
2972 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2986 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2987 bestproof->getPayoutScript()) == winners.end());
2995 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
3006 auto now = GetTime<std::chrono::seconds>();
3010 auto localWinnerProof =
3012 ProofId localWinnerProofId = localWinnerProof->getId();
3014 localWinnerProof->getId());
3023 for (
NodeId n = 0; n < 8; n++) {
3024 pm.
addNode(n, localWinnerProofId,
3028 return pm.setFinalized(peer.peerid);
3035 chaintip->
nTime = now.count();
3041 std::vector<ProofRef> acceptedContenderProofs;
3042 acceptedContenderProofs.push_back(localWinnerProof);
3049 for (
size_t numContenders = 2;
3053 m_node.avalanche->withPeerManager(
3059 if (rank <= bestRank) {
3061 acceptedContenderProofs.push_back(proof);
3062 const size_t numAccepted =
3064 acceptedContenderProofs.size());
3065 std::sort(acceptedContenderProofs.begin(),
3066 acceptedContenderProofs.begin() + numAccepted,
3068 const ProofId leftProofId = left->getId();
3069 const ProofId rightProofId = right->getId();
3070 const StakeContenderId leftContenderId(chaintipHash,
3072 const StakeContenderId rightContenderId(chaintipHash,
3074 return RewardRankComparator()(
3076 leftContenderId.ComputeProofRewardRank(
3077 MIN_VALID_PROOF_SCORE),
3078 leftProofId, rightContenderId,
3079 rightContenderId.ComputeProofRewardRank(
3080 MIN_VALID_PROOF_SCORE),
3085 std::vector<StakeContenderId> pollableContenders;
3086 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
3087 *
m_node.avalanche, chaintip, pollableContenders));
3089 pollableContenders.size(),
3094 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
3098 chaintipHash, acceptedContenderProofs[i]->getId());
3100 std::find(pollableContenders.begin(), pollableContenders.end(),
3101 acceptedContenderId) != pollableContenders.end());
3103 m_node.avalanche->getStakeContenderStatus(acceptedContenderId),
3108 std::set<StakeContenderId> unacceptedContenderIds(
3109 pollableContenders.begin(), pollableContenders.end());
3110 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
3112 chaintipHash, acceptedContenderProof->getId());
3113 unacceptedContenderIds.erase(acceptedContenderId);
3116 for (
auto cid : unacceptedContenderIds) {
3123 m_node.avalanche->getStakeContenderStatus(localWinnerContenderId),
3128BOOST_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.
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.
void clearInflightRequests(const std::map< CInv, uint8_t > &inflightRequests) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Decrement VoteRecord::inflight for each inventory by the given count.
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.