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 setVoteRecordSeed(
Processor &p, uint32_t seed) {
115 static void clearInvsNotWorthPolling(
Processor &p) {
121 const std::map<CInv, uint8_t> &itemCounts) {
142struct AvalancheProcessorTestingSetup :
public AvalancheTestChain100Setup {
143 AvalancheProcessorTestingSetup() : AvalancheTestChain100Setup() {
144 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
false);
147 AvalancheTest::setVoteRecordSeed(*
m_node.avalanche, 0);
155 new CNode(
id++,
nullptr, addr,
162 node->m_has_all_wanted_services =
166 node->fSuccessfullyConnected =
true;
168 m_connman->AddTestNode(*
node);
177 const uint32_t height = 100;
186 BOOST_CHECK(pb.addUTXO(outpoint, amount, height,
false, key));
191 return m_node.avalanche->withPeerManager(
193 return pm.
addNode(nodeid, proofid,
198 bool addNode(
NodeId nodeid) {
199 auto proof = GetProof();
200 return m_node.avalanche->withPeerManager(
203 pm.
addNode(nodeid, proof->getId(),
208 std::array<CNode *, 8> ConnectNodes() {
209 auto proof = GetProof();
212 return pm.registerProof(proof);
214 const ProofId &proofid = proof->getId();
216 std::array<CNode *, 8> nodes;
217 for (
CNode *&n : nodes) {
225 void runEventLoop() { AvalancheTest::runEventLoop(*
m_node.avalanche); }
227 NodeId getSuitableNodeToQuery() {
228 return AvalancheTest::getSuitableNodeToQuery(*
m_node.avalanche);
231 std::vector<CInv> getInvsForNextPoll(
bool forPoll =
false) {
232 return AvalancheTest::getInvsForNextPoll(*
m_node.avalanche, forPoll);
235 uint64_t getRound()
const {
236 return AvalancheTest::getRound(*
m_node.avalanche);
240 std::vector<avalanche::VoteItemUpdate> &updates,
241 std::string &error) {
248 std::vector<avalanche::VoteItemUpdate> &updates) {
256 return m_node.avalanche->addToReconcile(item);
259 void clearInvsNotWorthPolling() {
260 AvalancheTest::clearInvsNotWorthPolling(*
m_node.avalanche);
263 void clearInflightRequests(
const std::map<CInv, uint8_t> &itemCounts) {
264 AvalancheTest::clearInflightRequests(*
m_node.avalanche, itemCounts);
268struct BlockProvider {
269 AvalancheProcessorTestingSetup *fixture;
272 BlockProvider(AvalancheProcessorTestingSetup *_fixture)
273 : fixture(_fixture) {}
276 CBlock block = fixture->CreateAndProcessBlock({},
CScript());
280 return Assert(fixture->m_node.chainman)
281 ->m_blockman.LookupBlockIndex(blockHash);
288 std::vector<Vote> buildVotesForItems(uint32_t error,
289 std::vector<CBlockIndex *> &&items) {
290 size_t numItems = items.
size();
292 std::vector<Vote> votes;
293 votes.reserve(numItems);
298 votes.emplace_back(error, item->GetBlockHash());
306 pindex->nStatus = pindex->nStatus.withFailed();
310 return std::get<const CBlockIndex *>(item);
314struct ProofProvider {
315 AvalancheProcessorTestingSetup *fixture;
318 ProofProvider(AvalancheProcessorTestingSetup *_fixture)
319 : fixture(_fixture) {}
322 ProofRef proof = fixture->GetProof();
323 fixture->m_node.avalanche->withPeerManager(
331 return proof->
getId();
334 std::vector<Vote> buildVotesForItems(uint32_t error,
335 std::vector<ProofRef> &&items) {
336 size_t numItems = items.
size();
338 std::vector<Vote> votes;
339 votes.reserve(numItems);
343 for (
auto &item : items) {
344 votes.emplace_back(error, item->getId());
350 void invalidateItem(
const ProofRef &proof) {
351 fixture->m_node.avalanche->withPeerManager(
360 return std::get<const ProofRef>(item);
364struct StakeContenderProvider {
365 AvalancheProcessorTestingSetup *fixture;
367 std::vector<avalanche::VoteItemUpdate> updates;
370 StakeContenderProvider(AvalancheProcessorTestingSetup *_fixture)
371 : fixture(_fixture) {}
378 std::vector<CScript> winners;
379 if (!fixture->m_node.avalanche->getStakingRewardWinners(
383 const ProofRef proofWinner = fixture->GetProof();
385 fixture->m_node.avalanche->setStakingRewardWinners(chaintip,
390 const ProofRef proof = fixture->GetProof();
394 fixture->m_node.avalanche->withPeerManager(
401 fixture->m_node.avalanche->acceptStakeContender(contenderId);
403 BOOST_CHECK(fixture->m_node.avalanche->getStakeContenderStatus(
413 buildVotesForItems(uint32_t error, std::vector<StakeContenderId> &&items) {
414 size_t numItems = items.
size();
416 std::vector<Vote> votes;
417 votes.reserve(numItems);
420 std::sort(items.begin(), items.end(),
424 for (
auto &item : items) {
425 votes.emplace_back(error, item);
432 fixture->m_node.avalanche->rejectStakeContender(contenderId);
440 AvalancheTest::removeVoteRecord(*(fixture->m_node.avalanche),
445 return std::get<const StakeContenderId>(item);
450 AvalancheProcessorTestingSetup *fixture;
452 std::vector<avalanche::VoteItemUpdate> updates;
455 TxProvider(AvalancheProcessorTestingSetup *_fixture) : fixture(_fixture) {}
465 TestMemPoolEntryHelper mempoolEntryHelper;
466 auto entry = mempoolEntryHelper.Fee(1000 *
SATOSHI).FromTx(tx);
482 std::vector<Vote> buildVotesForItems(uint32_t error,
483 std::vector<CTransactionRef> &&items) {
484 size_t numItems = items.
size();
486 std::vector<Vote> votes;
487 votes.reserve(numItems);
490 std::sort(items.begin(), items.end(),
492 return lhs->GetId() < rhs->GetId();
494 for (
auto &item : items) {
495 votes.emplace_back(error, item->GetId());
511 return std::get<const CTransactionRef>(item);
517BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheProcessorTestingSetup)
521 StakeContenderProvider, TxProvider>;
523 boost::mpl::list<BlockProvider, ProofProvider, TxProvider>;
532 std::set<VoteStatus> status{
533 VoteStatus::Invalid, VoteStatus::Rejected, VoteStatus::Accepted,
534 VoteStatus::Finalized, VoteStatus::Stale,
537 auto item = provider.buildVoteItem();
539 for (
auto s : status) {
562 auto item = provider.buildVoteItem();
563 auto itemid = provider.getVoteItemId(item);
572 auto avanodes = ConnectNodes();
574 int nextNodeIndex = 0;
575 std::vector<avalanche::VoteItemUpdate> updates;
576 auto registerNewVote = [&](
const Response &resp) {
578 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
580 bool vote_is_registered = registerVotes(nodeid, resp, updates, error);
581 BOOST_CHECK_MESSAGE(vote_is_registered,
582 "registerVotes failed with error: " << error);
586 auto finalize = [&](
const auto finalizeItemId) {
587 Response resp = {getRound(), 0, {
Vote(0, finalizeItemId)}};
589 registerNewVote(next(resp));
590 if (updates.size() > 0) {
595 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
596 m_node.avalanche->setRecentlyFinalized(finalizeItemId);
603 auto finalizeNewItem = [&]() {
604 auto anotherItem = provider.buildVoteItem();
606 auto anotherItemId = provider.getVoteItemId(anotherItem);
609 AvalancheTest::addVoteRecord(*
m_node.avalanche, anotherVoteItem,
611 finalize(anotherItemId);
631 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
644 auto item =
decltype(provider.buildVoteItem())();
651 item = provider.buildVoteItem();
662 auto itemZero =
decltype(provider.buildVoteItem())();
675 auto item = provider.buildVoteItem();
685 const uint32_t invType = provider.invType;
687 auto item = provider.buildVoteItem();
688 auto itemid = provider.getVoteItemId(item);
691 auto avanodes = ConnectNodes();
699 auto invs = getInvsForNextPoll();
707 int nextNodeIndex = 0;
708 std::vector<avalanche::VoteItemUpdate> updates;
709 auto registerNewVote = [&](
const Response &resp) {
711 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
717 for (
int i = 0; i < 6; i++) {
718 registerNewVote(next(resp));
725 resp = {getRound(), 0, {
Vote(-1, itemid)}};
726 registerNewVote(next(resp));
731 resp = {getRound(), 0, {
Vote(0, itemid)}};
732 for (
int i = 1; i < 7; i++) {
733 registerNewVote(next(resp));
740 resp = {getRound(), 0, {
Vote(-1, itemid)}};
741 registerNewVote(next(resp));
745 registerNewVote(next(resp));
750 resp = {getRound(), 0, {
Vote(0, itemid)}};
751 for (
int i = 2; i < 8; i++) {
752 registerNewVote(next(resp));
760 registerNewVote(next(resp));
767 invs = getInvsForNextPoll();
773 registerNewVote(next(resp));
775 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
776 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
779 invs = getInvsForNextPoll();
783 item = provider.buildVoteItem();
784 itemid = provider.getVoteItemId(item);
788 invs = getInvsForNextPoll();
793 resp = {getRound(), 0, {
Vote(1, itemid)}};
794 for (
int i = 0; i < 6; i++) {
795 registerNewVote(next(resp));
801 registerNewVote(next(resp));
804 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
805 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
809 registerNewVote(next(resp));
815 invs = getInvsForNextPoll();
821 registerNewVote(next(resp));
824 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
825 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
828 invs = getInvsForNextPoll();
834 const uint32_t invType = provider.invType;
836 auto itemA = provider.buildVoteItem();
837 auto itemidA = provider.getVoteItemId(itemA);
839 auto itemB = provider.buildVoteItem();
840 auto itemidB = provider.getVoteItemId(itemB);
843 auto avanodes = ConnectNodes();
851 auto invs = getInvsForNextPoll();
856 uint64_t round = getRound();
858 std::vector<avalanche::VoteItemUpdate> updates;
860 {round, 0, {
Vote(0, itemidA)}}, updates));
864 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
867 invs = getInvsForNextPoll();
871 for (
size_t i = 0; i < invs.size(); i++) {
877 for (
int i = 0; i < 4; i++) {
878 NodeId nodeid = getSuitableNodeToQuery();
880 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
886 NodeId nodeid = getSuitableNodeToQuery();
888 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
894 NodeId firstNodeid = getSuitableNodeToQuery();
896 NodeId secondNodeid = getSuitableNodeToQuery();
902 BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates));
904 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemA);
905 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
908 invs = getInvsForNextPoll();
914 BOOST_CHECK(registerVotes(secondNodeid, resp, updates));
916 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemB);
917 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
920 invs = getInvsForNextPoll();
926 const uint32_t invType = provider.invType;
928 auto item = provider.buildVoteItem();
929 auto itemid = provider.getVoteItemId(item);
936 std::set<NodeId> avanodeIds;
937 auto avanodes = ConnectNodes();
938 for (
auto avanode : avanodes) {
940 avanodeIds.insert(avanode->GetId());
943 auto getSelectedAvanodeId = [&]() {
944 NodeId avanodeid = getSuitableNodeToQuery();
945 BOOST_CHECK(avanodeIds.find(avanodeid) != avanodeIds.end());
950 NodeId avanodeid = getSelectedAvanodeId();
954 auto invs = getInvsForNextPoll();
959 std::set<NodeId> unselectedNodeids = avanodeIds;
960 unselectedNodeids.erase(avanodeid);
961 const size_t remainingNodeIds = unselectedNodeids.size();
963 uint64_t round = getRound();
964 for (
size_t i = 0; i < remainingNodeIds; i++) {
969 NodeId nodeid = getSuitableNodeToQuery();
970 BOOST_CHECK(unselectedNodeids.find(nodeid) != avanodeIds.end());
971 unselectedNodeids.erase(nodeid);
981 std::vector<avalanche::VoteItemUpdate> updates;
982 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
989 auto checkRegisterVotesError = [&](
NodeId nodeid,
991 const std::string &expectedError) {
999 checkRegisterVotesError(avanodeid, next(resp),
"unexpected-ava-response");
1008 resp = {round, 0, {
Vote(0, itemid),
Vote(0, itemid)}};
1010 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
1014 resp = {getRound(), 0, {}};
1016 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
1020 resp = {getRound(), 0, {
Vote()}};
1022 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1027 resp = {getRound(), 0, {
Vote(0, itemid)}};
1029 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1033 invs = getInvsForNextPoll();
1037 uint64_t queryRound = getRound();
1040 resp = {queryRound + 1, 0, {
Vote()}};
1041 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1043 resp = {queryRound - 1, 0, {
Vote()}};
1044 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1048 resp = {queryRound, 0, {
Vote(0, itemid)}};
1049 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1052 resp = {queryRound, 0, {
Vote(0, itemid)}};
1053 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1058 const auto item2 = provider.buildVoteItem();
1061 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1062 resp = {getRound(), 0, {votes[1], votes[0]}};
1064 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1068 resp = {getRound(), 0, votes};
1070 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1077 const uint32_t invType = provider.invType;
1079 auto itemA = provider.buildVoteItem();
1080 auto itemB = provider.buildVoteItem();
1082 auto avanodes = ConnectNodes();
1083 int nextNodeIndex = 0;
1086 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1092 auto invs = getInvsForNextPoll();
1094 for (
size_t i = 0; i < invs.size(); i++) {
1100 provider.invalidateItem(itemB);
1102 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1103 std::vector<avalanche::VoteItemUpdate> updates;
1106 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1107 goodResp, updates));
1111 invs = getInvsForNextPoll();
1114 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1117 Response badResp{getRound(), 0, votes};
1121 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1122 badResp, updates, error));
1126 votes = provider.buildVotesForItems(1, {itemA});
1127 auto registerNewVote = [&]() {
1128 Response resp = {getRound(), 0, votes};
1130 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1131 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1133 for (
size_t i = 0; i < 4000; i++) {
1135 if (updates.size() > 0 &&
1136 updates[0].getStatus() == VoteStatus::Invalid) {
1142 invs = getInvsForNextPoll();
1146 badResp =
Response(getRound(), 0, votes);
1149 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1150 badResp, updates, error));
1154BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1159 auto queryTimeDuration = std::chrono::milliseconds(10);
1160 setArg(
"-avatimeout", ToString(queryTimeDuration.count()));
1162 setArg(
"-avalanchestakingpreconsensus",
"0");
1164 m_node.validation_signals->SyncWithValidationInterfaceQueue();
1169 AvalancheTest::setVoteRecordSeed(*
m_node.avalanche, 0);
1171 const auto item = provider.buildVoteItem();
1172 const auto itemid = provider.getVoteItemId(item);
1182 for (
int i = 0; i < 10; i++) {
1184 avanodeid = getSuitableNodeToQuery();
1186 auto start = Now<SteadyMilliseconds>();
1190 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1193 std::vector<avalanche::VoteItemUpdate> updates;
1194 bool ret = registerVotes(avanodeid, next(resp), updates);
1195 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1206 avanodeid = getSuitableNodeToQuery();
1210 std::this_thread::sleep_for(queryTimeDuration);
1212 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1218 const uint32_t invType = provider.invType;
1221 auto proof = GetProof();
1225 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1226 for (
auto &n : nodes) {
1232 const auto item = provider.buildVoteItem();
1233 const auto itemid = provider.getVoteItemId(item);
1237 std::map<NodeId, uint64_t> node_round_map;
1239 NodeId nodeid = getSuitableNodeToQuery();
1240 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1241 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1242 auto invs = getInvsForNextPoll();
1250 auto suitablenodeid = getSuitableNodeToQuery();
1252 auto invs = getInvsForNextPoll();
1258 auto it = node_round_map.begin();
1260 std::vector<avalanche::VoteItemUpdate> updates;
1261 BOOST_CHECK(registerVotes(it->first, resp, updates));
1262 node_round_map.erase(it);
1264 invs = getInvsForNextPoll();
1273 constexpr size_t numItems = 3;
1274 std::vector<CInv> itemInvs;
1275 itemInvs.reserve(numItems);
1276 for (
size_t i = 0; i < numItems; i++) {
1277 const auto item = provider.buildVoteItem();
1279 itemInvs.emplace_back(provider.invType, provider.getVoteItemId(item));
1282 auto contains = [](
const std::vector<CInv> &invs,
const CInv &target) {
1283 return std::find_if(invs.begin(), invs.end(), [&](
const CInv &inv) {
1284 return inv.type == target.type && inv.hash == target.hash;
1290 auto invs = getInvsForNextPoll(
true);
1297 clearInflightRequests(
1298 {{itemInvs[0], 1}, {itemInvs[1], 2}, {itemInvs[2], 3}});
1304 auto remaining = getInvsForNextPoll();
1313 auto remaining = getInvsForNextPoll();
1333 clearInflightRequests({});
1340 const uint32_t invType = provider.invType;
1342 auto proof = GetProof();
1349 std::vector<CNode *> nodes;
1350 nodes.reserve(numNodes);
1351 for (
size_t i = 0; i < numNodes; i++) {
1357 const auto item = provider.buildVoteItem();
1358 const auto itemid = provider.getVoteItemId(item);
1362 for (
CNode *n : nodes) {
1363 n->fDisconnect =
true;
1369 auto invs = getInvsForNextPoll();
1377 invs = getInvsForNextPoll();
1384 std::vector<VoteItemUpdate> updates;
1392 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1396 auto avanodes = ConnectNodes();
1405 uint64_t round = getRound();
1409 for (
size_t i = 0; i < avanodes.size(); i++) {
1411 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1415 const NodeId firstNodeId = getSuitableNodeToQuery();
1416 std::map<NodeId, uint64_t> node_round_map;
1418 for (
size_t i = 0; i < avanodes.size(); i++) {
1419 NodeId nodeid = getSuitableNodeToQuery();
1420 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1421 node_round_map[nodeid] = getRound();
1427 auto confidence =
m_node.avalanche->getConfidence(pindex);
1428 BOOST_REQUIRE(confidence > 0);
1430 for (
auto &[nodeid, r] : node_round_map) {
1431 if (nodeid == firstNodeId) {
1438 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1443 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1456 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1463 std::chrono::steady_clock::time_point start,
stop;
1473 auto avanodes = ConnectNodes();
1476 NodeId nodeid = getSuitableNodeToQuery();
1477 BOOST_CHECK_NE(nodeid,
NO_NODE);
1480 uint64_t queryRound = getRound();
1484 for (
int i = 0; i < 60 * 1000; i++) {
1488 if (getRound() == queryRound + avanodes.size()) {
1497 uint64_t responseRound = getRound();
1498 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1500 std::vector<VoteItemUpdate> updates;
1502 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1505 for (
int i = 0; i < 10000; i++) {
1508 if (getRound() != responseRound) {
1509 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1528 schedulerThread.join();
1533 std::chrono::steady_clock::time_point start,
stop;
1535 std::thread schedulerThread;
1544 m_node.validation_signals->SyncWithValidationInterfaceQueue();
1546 m_node.avalanche.reset();
1553 schedulerThread.join();
1560 auto addProofToReconcile = [&](uint32_t proofScore) {
1570 auto proof = addProofToReconcile(++score);
1572 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1581 for (
size_t i = 0; i < 10; i++) {
1582 auto proof = addProofToReconcile(++score);
1584 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1589 lastProofId = proof->
getId();
1592 for (
size_t i = 0; i < 10; i++) {
1593 auto proof = addProofToReconcile(--score);
1595 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1604 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1606 for (
auto &inv : invs) {
1607 BOOST_CHECK_NE(inv.hash, proof->
getId());
1613 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1614 setArg(
"-avalancheconflictingproofcooldown",
"0");
1628 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1629 coins.
AddCoin(conflictingOutpoint,
1632 coins.
AddCoin(immatureOutpoint,
1637 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1638 uint32_t height = 10) {
1645 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1646 auto validProof = buildProof(conflictingOutpoint, 2);
1647 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1698 int minStake = 400'000'000;
1699 setArg(
"-avaminquorumstake", ToString(minStake));
1700 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1712 setArg(
"-avaproof", localProof->ToHex());
1714 m_node.validation_signals->SyncWithValidationInterfaceQueue();
1720 AvalancheTest::setVoteRecordSeed(*
m_node.avalanche, 0);
1725 localProof->getId());
1729 AvalancheTest::getMinQuorumConnectedScoreRatio(*
m_node.avalanche), 0.5);
1751 for (
NodeId id = 0;
id < 8;
id++) {
1770 const int64_t tipTime =
1774 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1775 const int height = 100;
1776 const bool isCoinbase =
false;
1783 height, isCoinbase),
1788 auto proof2 = pb.
build();
1818 m_node.avalanche->withPeerManager(
1830 auto spendProofUtxo = [&](
ProofRef proof) {
1843 for (int64_t i = 0; i < 6; i++) {
1845 CreateAndProcessBlock({},
CScript());
1849 ->GetMedianTimePast(),
1850 proof2->getExpirationTime());
1861 spendProofUtxo(proof1);
1868 spendProofUtxo(
m_node.avalanche->getLocalProof());
1880 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1883 {
"",
"",
"",
false},
1884 {
"-1",
"-1",
"-1",
false},
1887 {
"-1",
"0",
"0",
false},
1888 {
"-0.01",
"0",
"0",
false},
1889 {
"21000000000000.01",
"0",
"0",
false},
1892 {
"0",
"-1",
"0",
false},
1893 {
"0",
"1.1",
"0",
false},
1896 {
"0",
"0",
"-1",
false},
1899 {
"0",
"0",
"0",
true},
1900 {
"0.00",
"0",
"0",
true},
1901 {
"0.01",
"0",
"0",
true},
1902 {
"1",
"0.1",
"0",
true},
1903 {
"10",
"0.5",
"0",
true},
1904 {
"10",
"1",
"0",
true},
1905 {
"21000000000000.00",
"0",
"0",
true},
1906 {
"0",
"0",
"1",
true},
1907 {
"0",
"0",
"100",
true},
1912 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1914 setArg(
"-avaminquorumstake", stake);
1915 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1916 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1939 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1940 setArg(
"-avaminavaproofsnodecount", ToString(minAvaproofsMessages));
1947 auto addNode = [&](
NodeId nodeid) {
1961 for (
NodeId id = 100;
id < 108;
id++) {
1966 minAvaproofsMessages <= 0);
1968 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1971 processor->avaproofsSent(i);
1975 processor->avaproofsSent(i);
1981 addNode(minAvaproofsMessages);
1982 processor->avaproofsSent(minAvaproofsMessages);
1986 AvalancheTest::clearavaproofsNodeCounter(*processor);
1990 checkMinAvaproofsMessages(0);
1991 checkMinAvaproofsMessages(1);
1992 checkMinAvaproofsMessages(10);
1993 checkMinAvaproofsMessages(100);
1998 setArg(
"-avastalevotethreshold",
2000 setArg(
"-avastalevotefactor",
"2");
2002 setArg(
"-avalanchestakingpreconsensus",
"0");
2004 const std::vector<std::tuple<int, int>> testCases = {
2010 m_node.validation_signals->SyncWithValidationInterfaceQueue();
2016 AvalancheTest::setVoteRecordSeed(*
m_node.avalanche, 0);
2022 const uint32_t invType = provider.invType;
2024 const auto item = provider.buildVoteItem();
2025 const auto itemid = provider.getVoteItemId(item);
2028 auto avanodes = ConnectNodes();
2029 int nextNodeIndex = 0;
2031 std::vector<avalanche::VoteItemUpdate> updates;
2032 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
2035 auto invs = getInvsForNextPoll();
2042 auto registerNewVote = [&](
const Response &resp) {
2044 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
2045 BOOST_CHECK(registerVotes(nodeid, resp, updates));
2049 for (
int i = 0; i < numYesVotes; i++) {
2051 registerNewVote(next(resp));
2054 i >= 6 ? i - 5 : 0);
2059 for (
int i = 0; i < numNeutralVotes; i++) {
2061 registerNewVote(next(resp));
2066 invs = getInvsForNextPoll();
2073 registerNewVote(next(resp));
2075 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
2076 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
2079 invs = getInvsForNextPoll();
2085 BlockProvider provider(
this);
2089 std::vector<CBlockIndex *> blockIndexes;
2093 blockIndexes.push_back(pindex);
2096 auto invs = getInvsForNextPoll();
2110 std::vector<Vote> votes;
2113 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
2114 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
2117 auto avanodes = ConnectNodes();
2118 int nextNodeIndex = 0;
2120 std::vector<avalanche::VoteItemUpdate> updates;
2121 auto registerNewVote = [&]() {
2122 Response resp = {getRound(), 0, votes};
2124 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
2125 BOOST_CHECK(registerVotes(nodeid, resp, updates));
2131 bool eleventhBlockFinalized =
false;
2132 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
2135 for (
auto &update : updates) {
2136 if (update.getStatus() == VoteStatus::Finalized &&
2137 provider.fromAnyVoteItem(update.getVoteItem())
2138 ->GetBlockHash() == eleventhBlockHash) {
2139 eleventhBlockFinalized =
true;
2150 clearInvsNotWorthPolling();
2151 invs = getInvsForNextPoll();
2153 for (
size_t i = 0; i < 10; i++) {
2168 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2170 activeChainstate.InvalidateBlock(state, tip);
2176 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2184 activeChainstate.ResetBlockFailureFlags(tip);
2186 activeChainstate.ActivateBestChain(state);
2190 clearInvsNotWorthPolling();
2191 invs = getInvsForNextPoll();
2198 for (
auto &inv : invs) {
2199 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2202 bool tipFinalized =
false;
2203 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2206 for (
auto &update : updates) {
2207 if (update.getStatus() == VoteStatus::Finalized &&
2208 provider.fromAnyVoteItem(update.getVoteItem())
2209 ->GetBlockHash() == tiphash) {
2210 tipFinalized =
true;
2219 clearInvsNotWorthPolling();
2220 invs = getInvsForNextPoll();
2228 BlockHash alttiphash = alttip->GetBlockHash();
2229 votes = {{1, alttiphash}};
2231 bool alttipInvalidated =
false;
2232 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2235 for (
auto &update : updates) {
2236 if (update.getStatus() == VoteStatus::Invalid &&
2237 provider.fromAnyVoteItem(update.getVoteItem())
2238 ->GetBlockHash() == alttiphash) {
2239 alttipInvalidated =
true;
2244 invs = getInvsForNextPoll();
2255 const int numberElementsEachType = 100;
2258 std::vector<ProofRef> proofs;
2259 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2263 proofs.emplace_back(std::move(proof));
2265 Shuffle(proofs.begin(), proofs.end(), rng);
2267 std::vector<CBlockIndex> indexes;
2268 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2271 indexes.emplace_back(std::move(index));
2273 Shuffle(indexes.begin(), indexes.end(), rng);
2275 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2276 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2282 for (
size_t i = 0; i < numberElementsEachType; i++) {
2284 const size_t firstType = rng.
randrange(numTypes);
2286 for (
size_t j = 0; j < numTypes; j++) {
2287 switch ((firstType + j) % numTypes) {
2290 writeView->insert(std::make_pair(
2291 std::get<0>(allItems)[i],
VoteRecord(
true)));
2295 writeView->insert(std::make_pair(
2296 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2307 auto readView = voteMap.getReadView();
2308 auto it = readView.begin();
2311 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2312 for (
size_t i = 0; i < numberElementsEachType; i++) {
2313 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2315 uint32_t currentScore =
2316 std::get<const ProofRef>(it->first)->getScore();
2317 BOOST_CHECK_LT(currentScore, lastScore);
2318 lastScore = currentScore;
2326 for (
size_t i = 0; i < numberElementsEachType; i++) {
2327 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2330 std::get<const CBlockIndex *>(it->first)->nChainWork;
2332 lastWork = currentWork;
2345 const auto block = std::make_shared<const CBlock>(
2346 this->CreateBlock({},
CScript(), chainstate));
2373 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
2383 auto now = GetTime<std::chrono::seconds>();
2389 std::vector<CScript> winners;
2392 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2397 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2402 prevBlock.
nTime = now.count();
2407 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2410 size_t numProofs = 10;
2411 std::vector<ProofRef> proofs;
2412 proofs.reserve(numProofs);
2413 for (
size_t i = 0; i < numProofs; i++) {
2417 auto proof = GetProof(payoutScript);
2424 return pm.setFinalized(peer.peerid);
2428 proofs.emplace_back(std::move(proof));
2436 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2439 auto winnerExists = [&](
const CScript &expectedWinner) {
2440 const std::string winnerString =
FormatScript(expectedWinner);
2442 for (
const ProofRef &proof : proofs) {
2453 prevBlock.
nTime = now.count();
2458 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2464 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2470 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2474 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2479 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2483 m_node.avalanche->cleanupStakingRewards(101);
2487 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2491 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2497 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2501 m_node.avalanche->cleanupStakingRewards(200);
2505 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2507 !
m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2519 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2525 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2533 auto localProof = buildProof(outpoint, 1, 100);
2536 setArg(
"-avaproof", localProof->ToHex());
2537 setArg(
"-avalancheconflictingproofcooldown",
"0");
2538 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2539 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2541 m_node.validation_signals->SyncWithValidationInterfaceQueue();
2547 AvalancheTest::setVoteRecordSeed(*
m_node.avalanche, 0);
2550 localProof->getId());
2552 auto checkLocalProofState = [&](
const bool boundToPeer,
2557 return pm.isBoundToPeer(localProof->getId());
2560 BOOST_CHECK_MESSAGE(
2561 m_node.avalanche->getLocalProofRegistrationState().GetResult() ==
2563 m_node.avalanche->getLocalProofRegistrationState().ToString());
2566 checkLocalProofState(
false, ProofRegistrationResult::NONE);
2570 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2571 checkLocalProofState(
false, ProofRegistrationResult::NONE);
2574 AvalancheTest::setLocalProofShareable(*
m_node.avalanche,
true);
2576 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2577 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2581 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2582 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2586 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2587 checkLocalProofState(
true, ProofRegistrationResult::NONE);
2590 auto conflictingProof = buildProof(outpoint, 2, 100);
2596 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2597 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2601 setArg(
"-avalancheconflictingproofcooldown",
"0");
2602 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2622 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2629 auto proof = buildProof(outpoint, 1);
2648 AvalancheTest::addProofToRecentfinalized(*
m_node.avalanche, proof->
getId());
2655 return peer.hasFinalized;
2662 auto betterProof = buildProof(outpoint, 2);
2684 m_node.validation_signals->SyncWithValidationInterfaceQueue();
2692 auto now = GetTime<std::chrono::seconds>();
2695 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
true);
2696 AvalancheTest::setVoteRecordSeed(*
m_node.avalanche, 0);
2704 const ProofId proofid1 = proof1->getId();
2709 const ProofId proofid2 = proof2->getId();
2720 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2722 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2728 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2733 for (
NodeId n = 0; n < 8; n++) {
2738 return pm.setFinalized(peer.peerid);
2750 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2751 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2757 std::vector<CScript> winners;
2761 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2766 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2770 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2772 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2778 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2784 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2792 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2795 m_node.avalanche->getStakeContenderStatus(contender1_block1), -1);
2797 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2800 m_node.avalanche->getStakeContenderStatus(contender2_block1), -1);
2802 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2805 m_node.avalanche->setStakingRewardWinners(
2806 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2811 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2814 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2817 m_node.avalanche->withPeerManager(
2823 const ProofId proofid3 = proof3->getId();
2826 for (
NodeId n = 0; n < 8; n++) {
2832 block = CreateAndProcessBlock({},
CScript());
2835 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2836 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2840 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2844 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2846 m_node.avalanche->getStakeContenderStatus(contender2_block2), -1);
2853 m_node.avalanche->getStakeContenderStatus(contender1_block3), -1);
2857 m_node.avalanche->getStakeContenderStatus(contender2_block3), -1);
2860 m_node.avalanche->withPeerManager(
2864 size_t numProofs = 8;
2865 std::vector<ProofRef> proofs;
2866 proofs.reserve(numProofs);
2867 for (
size_t i = 0; i < numProofs; i++) {
2876 return pm.setFinalized(peer.peerid);
2879 proofs.emplace_back(std::move(proof));
2884 const ProofId proofid = proofs[0]->getId();
2885 for (
NodeId n = 0; n < 8; n++) {
2895 std::vector<CScript> winners;
2896 for (
int attempt = 0; attempt < 10; attempt++) {
2898 block = CreateAndProcessBlock({},
CScript());
2901 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2902 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2908 chaintip->GetBlockHash(), winners));
2909 if (winners.size() == 8) {
2917 size_t numAccepted = 0;
2918 for (
const auto &proof : proofs) {
2922 if (
m_node.avalanche->getStakeContenderStatus(contender) == 0) {
2924 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2932 block = CreateAndProcessBlock({},
CScript());
2935 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2940 m_node.avalanche->withPeerManager(
2942 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2951 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2952 bestproof->getPayoutScript()) == winners.end());
2959 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2970 block = CreateAndProcessBlock({},
CScript());
2973 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2974 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2975 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
2982 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2996 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2997 bestproof->getPayoutScript()) == winners.end());
3004 m_node.avalanche->getStakeContenderStatus(bestcontender), 4);
3015 auto now = GetTime<std::chrono::seconds>();
3019 auto localWinnerProof =
3021 ProofId localWinnerProofId = localWinnerProof->getId();
3023 localWinnerProof->getId());
3029 chaintip->
nTime = (now + registration_delay).
count();
3035 for (
NodeId n = 0; n < 8; n++) {
3036 pm.
addNode(n, localWinnerProofId,
3040 return pm.setFinalized(peer.peerid);
3045 now += registration_delay;
3052 std::vector<ProofRef> acceptedContenderProofs;
3053 acceptedContenderProofs.push_back(localWinnerProof);
3060 for (
size_t numContenders = 2;
3064 m_node.avalanche->withPeerManager(
3070 if (rank <= bestRank) {
3072 acceptedContenderProofs.push_back(proof);
3073 const size_t numAccepted =
3075 acceptedContenderProofs.size());
3076 std::sort(acceptedContenderProofs.begin(),
3077 acceptedContenderProofs.begin() + numAccepted,
3079 const ProofId leftProofId = left->getId();
3080 const ProofId rightProofId = right->getId();
3081 const StakeContenderId leftContenderId(chaintipHash,
3083 const StakeContenderId rightContenderId(chaintipHash,
3085 return RewardRankComparator()(
3087 leftContenderId.ComputeProofRewardRank(
3088 MIN_VALID_PROOF_SCORE),
3089 leftProofId, rightContenderId,
3090 rightContenderId.ComputeProofRewardRank(
3091 MIN_VALID_PROOF_SCORE),
3096 std::vector<StakeContenderId> pollableContenders;
3097 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
3098 *
m_node.avalanche, chaintip, pollableContenders));
3100 pollableContenders.size(),
3105 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
3109 chaintipHash, acceptedContenderProofs[i]->getId());
3111 std::find(pollableContenders.begin(), pollableContenders.end(),
3112 acceptedContenderId) != pollableContenders.end());
3114 m_node.avalanche->getStakeContenderStatus(acceptedContenderId),
3119 std::set<StakeContenderId> unacceptedContenderIds(
3120 pollableContenders.begin(), pollableContenders.end());
3121 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
3123 chaintipHash, acceptedContenderProof->getId());
3124 unacceptedContenderIds.erase(acceptedContenderId);
3127 for (
auto cid : unacceptedContenderIds) {
3134 m_node.avalanche->getStakeContenderStatus(localWinnerContenderId),
3139BOOST_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.
An outpoint - a combination of a transaction hash and an index n into its vout.
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.
Serialized script, used inside transaction inputs and outputs.
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.
static std::unique_ptr< Processor > MakeProcessor(const ArgsManager &argsman, interfaces::Chain &chain, CConnman *connman, ChainstateManager &chainman, CTxMemPool *mempoolIn, CScheduler &scheduler, bilingual_str &error)
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::optional< uint32_t > m_voteRecordSeed
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
static uint32_t amountToScore(Amount amount)
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()
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.