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/test/unit_test.hpp>
42 struct AvalancheTest {
45 static std::vector<CInv> getInvsForNextPoll(
Processor &p) {
53 return p.peerManager->selectNode());
58 static uint32_t getMinQuorumScore(
const Processor &p) {
62 static double getMinQuorumConnectedScoreRatio(
const Processor &p) {
66 static void clearavaproofsNodeCounter(
Processor &p) {
73 std::make_pair(item, voteRecord));
80 static void setFinalizationTip(
Processor &p,
83 p.finalizationTip = pindex;
86 static void setLocalProofShareable(
Processor &p,
bool shareable) {
92 static void addProofToRecentfinalized(
Processor &p,
95 return p.finalizedItems.insert(proofid));
98 static bool setContenderStatusForLocalWinners(
100 std::vector<StakeContenderId> &pollableContenders) {
105 static void setStakingPreconsensus(
Processor &p,
bool enabled) {
109 static void clearInvsNotWorthPolling(
Processor &p) {
129struct AvalancheProcessorTestingSetup :
public AvalancheTestChain100Setup {
130 AvalancheProcessorTestingSetup() : AvalancheTestChain100Setup() {
131 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
false);
139 new CNode(
id++,
nullptr, addr,
146 node->m_has_all_wanted_services =
150 node->fSuccessfullyConnected =
true;
152 m_connman->AddTestNode(*
node);
161 const uint32_t height = 100;
170 BOOST_CHECK(pb.addUTXO(outpoint, amount, height,
false, key));
175 return m_node.avalanche->withPeerManager(
177 return pm.
addNode(nodeid, proofid,
182 bool addNode(
NodeId nodeid) {
183 auto proof = GetProof();
184 return m_node.avalanche->withPeerManager(
187 pm.
addNode(nodeid, proof->getId(),
192 std::array<CNode *, 8> ConnectNodes() {
193 auto proof = GetProof();
196 return pm.registerProof(proof);
198 const ProofId &proofid = proof->getId();
200 std::array<CNode *, 8> nodes;
201 for (
CNode *&n : nodes) {
209 void runEventLoop() { AvalancheTest::runEventLoop(*
m_node.avalanche); }
211 NodeId getSuitableNodeToQuery() {
212 return AvalancheTest::getSuitableNodeToQuery(*
m_node.avalanche);
215 std::vector<CInv> getInvsForNextPoll() {
216 return AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
219 uint64_t getRound()
const {
220 return AvalancheTest::getRound(*
m_node.avalanche);
224 std::vector<avalanche::VoteItemUpdate> &updates,
225 std::string &error) {
232 std::vector<avalanche::VoteItemUpdate> &updates) {
240 return m_node.avalanche->addToReconcile(item);
243 void clearInvsNotWorthPolling() {
244 AvalancheTest::clearInvsNotWorthPolling(*
m_node.avalanche);
248struct BlockProvider {
249 AvalancheProcessorTestingSetup *fixture;
252 BlockProvider(AvalancheProcessorTestingSetup *_fixture)
253 : fixture(_fixture) {}
256 CBlock block = fixture->CreateAndProcessBlock({}, CScript());
260 return Assert(fixture->m_node.chainman)
261 ->m_blockman.LookupBlockIndex(blockHash);
268 std::vector<Vote> buildVotesForItems(uint32_t error,
269 std::vector<CBlockIndex *> &&items) {
270 size_t numItems = items.
size();
272 std::vector<Vote> votes;
273 votes.reserve(numItems);
278 votes.emplace_back(error, item->GetBlockHash());
286 pindex->nStatus = pindex->nStatus.withFailed();
290 return std::get<const CBlockIndex *>(item);
294struct ProofProvider {
295 AvalancheProcessorTestingSetup *fixture;
298 ProofProvider(AvalancheProcessorTestingSetup *_fixture)
299 : fixture(_fixture) {}
302 ProofRef proof = fixture->GetProof();
303 fixture->m_node.avalanche->withPeerManager(
311 return proof->
getId();
314 std::vector<Vote> buildVotesForItems(uint32_t error,
315 std::vector<ProofRef> &&items) {
316 size_t numItems = items.
size();
318 std::vector<Vote> votes;
319 votes.reserve(numItems);
323 for (
auto &item : items) {
324 votes.emplace_back(error, item->getId());
330 void invalidateItem(
const ProofRef &proof) {
331 fixture->m_node.avalanche->withPeerManager(
340 return std::get<const ProofRef>(item);
344struct StakeContenderProvider {
345 AvalancheProcessorTestingSetup *fixture;
347 std::vector<avalanche::VoteItemUpdate> updates;
350 StakeContenderProvider(AvalancheProcessorTestingSetup *_fixture)
351 : fixture(_fixture) {}
358 std::vector<CScript> winners;
359 if (!fixture->m_node.avalanche->getStakingRewardWinners(
363 const ProofRef proofWinner = fixture->GetProof();
365 fixture->m_node.avalanche->setStakingRewardWinners(chaintip,
370 const ProofRef proof = fixture->GetProof();
374 fixture->m_node.avalanche->withPeerManager(
381 fixture->m_node.avalanche->acceptStakeContender(contenderId);
383 BOOST_CHECK(fixture->m_node.avalanche->getStakeContenderStatus(
393 buildVotesForItems(uint32_t error, std::vector<StakeContenderId> &&items) {
394 size_t numItems = items.
size();
396 std::vector<Vote> votes;
397 votes.reserve(numItems);
400 std::sort(items.begin(), items.end(),
404 for (
auto &item : items) {
405 votes.emplace_back(error, item);
412 fixture->m_node.avalanche->rejectStakeContender(contenderId);
420 AvalancheTest::removeVoteRecord(*(fixture->m_node.avalanche),
425 return std::get<const StakeContenderId>(item);
430 AvalancheProcessorTestingSetup *fixture;
432 std::vector<avalanche::VoteItemUpdate> updates;
435 TxProvider(AvalancheProcessorTestingSetup *_fixture) : fixture(_fixture) {}
445 TestMemPoolEntryHelper mempoolEntryHelper;
446 auto entry = mempoolEntryHelper.Fee(1000 *
SATOSHI).FromTx(tx);
462 std::vector<Vote> buildVotesForItems(uint32_t error,
463 std::vector<CTransactionRef> &&items) {
464 size_t numItems = items.
size();
466 std::vector<Vote> votes;
467 votes.reserve(numItems);
470 std::sort(items.begin(), items.end(),
472 return lhs->GetId() < rhs->GetId();
474 for (
auto &item : items) {
475 votes.emplace_back(error, item->GetId());
491 return std::get<const CTransactionRef>(item);
497BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheProcessorTestingSetup)
501 StakeContenderProvider, TxProvider>;
503 boost::mpl::list<BlockProvider, ProofProvider, TxProvider>;
512 std::set<VoteStatus> status{
513 VoteStatus::Invalid, VoteStatus::Rejected, VoteStatus::Accepted,
514 VoteStatus::Finalized, VoteStatus::Stale,
517 auto item = provider.buildVoteItem();
519 for (
auto s : status) {
542 auto item = provider.buildVoteItem();
543 auto itemid = provider.getVoteItemId(item);
552 auto avanodes = ConnectNodes();
554 int nextNodeIndex = 0;
555 std::vector<avalanche::VoteItemUpdate> updates;
556 auto registerNewVote = [&](
const Response &resp) {
558 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
563 auto finalize = [&](
const auto finalizeItemId) {
564 Response resp = {getRound(), 0, {
Vote(0, finalizeItemId)}};
566 registerNewVote(next(resp));
567 if (updates.size() > 0) {
572 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
573 m_node.avalanche->setRecentlyFinalized(finalizeItemId);
580 auto finalizeNewItem = [&]() {
581 auto anotherItem = provider.buildVoteItem();
583 auto anotherItemId = provider.getVoteItemId(anotherItem);
586 AvalancheTest::addVoteRecord(*
m_node.avalanche, anotherVoteItem,
588 finalize(anotherItemId);
608 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
621 auto item =
decltype(provider.buildVoteItem())();
628 item = provider.buildVoteItem();
639 auto itemZero =
decltype(provider.buildVoteItem())();
652 auto item = provider.buildVoteItem();
662 const uint32_t invType = provider.invType;
664 auto item = provider.buildVoteItem();
665 auto itemid = provider.getVoteItemId(item);
668 auto avanodes = ConnectNodes();
676 auto invs = getInvsForNextPoll();
684 int nextNodeIndex = 0;
685 std::vector<avalanche::VoteItemUpdate> updates;
686 auto registerNewVote = [&](
const Response &resp) {
688 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
694 for (
int i = 0; i < 6; i++) {
695 registerNewVote(next(resp));
702 resp = {getRound(), 0, {
Vote(-1, itemid)}};
703 registerNewVote(next(resp));
708 resp = {getRound(), 0, {
Vote(0, itemid)}};
709 for (
int i = 1; i < 7; i++) {
710 registerNewVote(next(resp));
717 resp = {getRound(), 0, {
Vote(-1, itemid)}};
718 registerNewVote(next(resp));
722 registerNewVote(next(resp));
727 resp = {getRound(), 0, {
Vote(0, itemid)}};
728 for (
int i = 2; i < 8; i++) {
729 registerNewVote(next(resp));
737 registerNewVote(next(resp));
744 invs = getInvsForNextPoll();
750 registerNewVote(next(resp));
752 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
753 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
756 invs = getInvsForNextPoll();
760 item = provider.buildVoteItem();
761 itemid = provider.getVoteItemId(item);
765 invs = getInvsForNextPoll();
770 resp = {getRound(), 0, {
Vote(1, itemid)}};
771 for (
int i = 0; i < 6; i++) {
772 registerNewVote(next(resp));
778 registerNewVote(next(resp));
781 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
782 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
786 registerNewVote(next(resp));
792 invs = getInvsForNextPoll();
798 registerNewVote(next(resp));
801 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
802 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
805 invs = getInvsForNextPoll();
811 const uint32_t invType = provider.invType;
813 auto itemA = provider.buildVoteItem();
814 auto itemidA = provider.getVoteItemId(itemA);
816 auto itemB = provider.buildVoteItem();
817 auto itemidB = provider.getVoteItemId(itemB);
820 auto avanodes = ConnectNodes();
828 auto invs = getInvsForNextPoll();
833 uint64_t round = getRound();
835 std::vector<avalanche::VoteItemUpdate> updates;
837 {round, 0, {
Vote(0, itemidA)}}, updates));
841 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
844 invs = getInvsForNextPoll();
848 for (
size_t i = 0; i < invs.size(); i++) {
854 for (
int i = 0; i < 4; i++) {
855 NodeId nodeid = getSuitableNodeToQuery();
857 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
863 NodeId nodeid = getSuitableNodeToQuery();
865 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
871 NodeId firstNodeid = getSuitableNodeToQuery();
873 NodeId secondNodeid = getSuitableNodeToQuery();
879 BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates));
881 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemA);
882 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
885 invs = getInvsForNextPoll();
891 BOOST_CHECK(registerVotes(secondNodeid, resp, updates));
893 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemB);
894 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
897 invs = getInvsForNextPoll();
903 const uint32_t invType = provider.invType;
905 auto item = provider.buildVoteItem();
906 auto itemid = provider.getVoteItemId(item);
913 std::set<NodeId> avanodeIds;
914 auto avanodes = ConnectNodes();
915 for (
auto avanode : avanodes) {
917 avanodeIds.insert(avanode->GetId());
920 auto getSelectedAvanodeId = [&]() {
921 NodeId avanodeid = getSuitableNodeToQuery();
922 BOOST_CHECK(avanodeIds.find(avanodeid) != avanodeIds.end());
927 NodeId avanodeid = getSelectedAvanodeId();
931 auto invs = getInvsForNextPoll();
936 std::set<NodeId> unselectedNodeids = avanodeIds;
937 unselectedNodeids.erase(avanodeid);
938 const size_t remainingNodeIds = unselectedNodeids.size();
940 uint64_t round = getRound();
941 for (
size_t i = 0; i < remainingNodeIds; i++) {
946 NodeId nodeid = getSuitableNodeToQuery();
947 BOOST_CHECK(unselectedNodeids.find(nodeid) != avanodeIds.end());
948 unselectedNodeids.erase(nodeid);
958 std::vector<avalanche::VoteItemUpdate> updates;
959 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
966 auto checkRegisterVotesError = [&](
NodeId nodeid,
968 const std::string &expectedError) {
976 checkRegisterVotesError(avanodeid, next(resp),
"unexpected-ava-response");
985 resp = {round, 0, {
Vote(0, itemid),
Vote(0, itemid)}};
987 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
991 resp = {getRound(), 0, {}};
993 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
997 resp = {getRound(), 0, {
Vote()}};
999 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1006 invs = getInvsForNextPoll();
1009 item = provider.buildVoteItem();
1010 itemid = provider.getVoteItemId(item);
1013 invs = getInvsForNextPoll();
1017 uint64_t queryRound = getRound();
1020 resp = {queryRound + 1, 0, {
Vote()}};
1021 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1023 resp = {queryRound - 1, 0, {
Vote()}};
1024 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1028 resp = {queryRound, 0, {
Vote(0, itemid)}};
1029 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1032 resp = {queryRound, 0, {
Vote(0, itemid)}};
1033 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1038 const auto item2 = provider.buildVoteItem();
1041 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1042 resp = {getRound(), 0, {votes[1], votes[0]}};
1044 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1048 resp = {getRound(), 0, votes};
1050 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1057 const uint32_t invType = provider.invType;
1059 auto itemA = provider.buildVoteItem();
1060 auto itemB = provider.buildVoteItem();
1062 auto avanodes = ConnectNodes();
1063 int nextNodeIndex = 0;
1066 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1072 auto invs = getInvsForNextPoll();
1074 for (
size_t i = 0; i < invs.size(); i++) {
1080 provider.invalidateItem(itemB);
1082 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1083 std::vector<avalanche::VoteItemUpdate> updates;
1086 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1087 goodResp, updates));
1091 invs = getInvsForNextPoll();
1094 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1097 Response badResp{getRound(), 0, votes};
1101 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1102 badResp, updates, error));
1106 votes = provider.buildVotesForItems(1, {itemA});
1107 auto registerNewVote = [&]() {
1108 Response resp = {getRound(), 0, votes};
1110 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1111 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1113 for (
size_t i = 0; i < 4000; i++) {
1115 if (updates.size() > 0 &&
1116 updates[0].getStatus() == VoteStatus::Invalid) {
1122 invs = getInvsForNextPoll();
1126 badResp =
Response(getRound(), 0, votes);
1129 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1130 badResp, updates, error));
1134BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1139 auto queryTimeDuration = std::chrono::milliseconds(10);
1140 setArg(
"-avatimeout",
ToString(queryTimeDuration.count()));
1142 setArg(
"-avalanchestakingpreconsensus",
"0");
1145 m_node.avalanche = Processor::MakeProcessor(
1149 const auto item = provider.buildVoteItem();
1150 const auto itemid = provider.getVoteItemId(item);
1160 for (
int i = 0; i < 10; i++) {
1162 avanodeid = getSuitableNodeToQuery();
1164 auto start = Now<SteadyMilliseconds>();
1168 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1171 std::vector<avalanche::VoteItemUpdate> updates;
1172 bool ret = registerVotes(avanodeid, next(resp), updates);
1173 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1184 avanodeid = getSuitableNodeToQuery();
1188 std::this_thread::sleep_for(queryTimeDuration);
1190 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1196 const uint32_t invType = provider.invType;
1199 auto proof = GetProof();
1203 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1204 for (
auto &n : nodes) {
1210 const auto item = provider.buildVoteItem();
1211 const auto itemid = provider.getVoteItemId(item);
1215 std::map<NodeId, uint64_t> node_round_map;
1217 NodeId nodeid = getSuitableNodeToQuery();
1218 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1219 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1220 auto invs = getInvsForNextPoll();
1228 auto suitablenodeid = getSuitableNodeToQuery();
1230 auto invs = getInvsForNextPoll();
1236 auto it = node_round_map.begin();
1238 std::vector<avalanche::VoteItemUpdate> updates;
1239 BOOST_CHECK(registerVotes(it->first, resp, updates));
1240 node_round_map.erase(it);
1242 invs = getInvsForNextPoll();
1249 std::vector<VoteItemUpdate> updates;
1251 CBlock block = CreateAndProcessBlock({}, CScript());
1257 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1261 auto avanodes = ConnectNodes();
1270 uint64_t round = getRound();
1274 for (
size_t i = 0; i < avanodes.size(); i++) {
1276 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1280 const NodeId firstNodeId = getSuitableNodeToQuery();
1281 std::map<NodeId, uint64_t> node_round_map;
1283 for (
size_t i = 0; i < avanodes.size(); i++) {
1284 NodeId nodeid = getSuitableNodeToQuery();
1285 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1286 node_round_map[nodeid] = getRound();
1292 auto confidence =
m_node.avalanche->getConfidence(pindex);
1293 BOOST_REQUIRE(confidence > 0);
1295 for (
auto &[nodeid, r] : node_round_map) {
1296 if (nodeid == firstNodeId) {
1303 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1308 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1315 CBlock block = CreateAndProcessBlock({}, CScript());
1321 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1328 std::chrono::steady_clock::time_point start,
stop;
1338 auto avanodes = ConnectNodes();
1341 NodeId nodeid = getSuitableNodeToQuery();
1342 BOOST_CHECK_NE(nodeid,
NO_NODE);
1345 uint64_t queryRound = getRound();
1349 for (
int i = 0; i < 60 * 1000; i++) {
1353 if (getRound() == queryRound + avanodes.size()) {
1362 uint64_t responseRound = getRound();
1363 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1365 std::vector<VoteItemUpdate> updates;
1367 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1370 for (
int i = 0; i < 10000; i++) {
1373 if (getRound() != responseRound) {
1374 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1393 schedulerThread.join();
1398 std::chrono::steady_clock::time_point start,
stop;
1400 std::thread schedulerThread;
1410 m_node.avalanche.reset();
1417 schedulerThread.join();
1424 auto addProofToReconcile = [&](uint32_t proofScore) {
1434 auto proof = addProofToReconcile(++score);
1436 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1445 for (
size_t i = 0; i < 10; i++) {
1446 auto proof = addProofToReconcile(++score);
1448 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1453 lastProofId = proof->
getId();
1456 for (
size_t i = 0; i < 10; i++) {
1457 auto proof = addProofToReconcile(--score);
1459 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1468 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1470 for (
auto &inv : invs) {
1471 BOOST_CHECK_NE(inv.hash, proof->
getId());
1477 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1478 setArg(
"-avalancheconflictingproofcooldown",
"0");
1492 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1493 coins.
AddCoin(conflictingOutpoint,
1496 coins.
AddCoin(immatureOutpoint,
1501 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1502 uint32_t height = 10) {
1509 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1510 auto validProof = buildProof(conflictingOutpoint, 2);
1511 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1562 int minStake = 400'000'000;
1563 setArg(
"-avaminquorumstake",
ToString(minStake));
1564 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1568 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1576 setArg(
"-avaproof", localProof->ToHex());
1580 m_node.avalanche = Processor::MakeProcessor(
1587 localProof->getId());
1591 AvalancheTest::getMinQuorumConnectedScoreRatio(*
m_node.avalanche), 0.5);
1613 for (
NodeId id = 0;
id < 8;
id++) {
1632 const int64_t tipTime =
1636 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1637 const int height = 100;
1638 const bool isCoinbase =
false;
1645 height, isCoinbase),
1650 auto proof2 = pb.
build();
1680 m_node.avalanche->withPeerManager(
1692 auto spendProofUtxo = [&](
ProofRef proof) {
1705 for (int64_t i = 0; i < 6; i++) {
1707 CreateAndProcessBlock({}, CScript());
1711 ->GetMedianTimePast(),
1712 proof2->getExpirationTime());
1723 spendProofUtxo(proof1);
1730 spendProofUtxo(
m_node.avalanche->getLocalProof());
1742 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1745 {
"",
"",
"",
false},
1746 {
"-1",
"-1",
"-1",
false},
1749 {
"-1",
"0",
"0",
false},
1750 {
"-0.01",
"0",
"0",
false},
1751 {
"21000000000000.01",
"0",
"0",
false},
1754 {
"0",
"-1",
"0",
false},
1755 {
"0",
"1.1",
"0",
false},
1758 {
"0",
"0",
"-1",
false},
1761 {
"0",
"0",
"0",
true},
1762 {
"0.00",
"0",
"0",
true},
1763 {
"0.01",
"0",
"0",
true},
1764 {
"1",
"0.1",
"0",
true},
1765 {
"10",
"0.5",
"0",
true},
1766 {
"10",
"1",
"0",
true},
1767 {
"21000000000000.00",
"0",
"0",
true},
1768 {
"0",
"0",
"1",
true},
1769 {
"0",
"0",
"100",
true},
1774 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1776 setArg(
"-avaminquorumstake", stake);
1777 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1778 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1781 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1801 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1802 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1805 auto processor = Processor::MakeProcessor(
1809 auto addNode = [&](
NodeId nodeid) {
1823 for (
NodeId id = 100;
id < 108;
id++) {
1828 minAvaproofsMessages <= 0);
1830 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1833 processor->avaproofsSent(i);
1837 processor->avaproofsSent(i);
1843 addNode(minAvaproofsMessages);
1844 processor->avaproofsSent(minAvaproofsMessages);
1848 AvalancheTest::clearavaproofsNodeCounter(*processor);
1852 checkMinAvaproofsMessages(0);
1853 checkMinAvaproofsMessages(1);
1854 checkMinAvaproofsMessages(10);
1855 checkMinAvaproofsMessages(100);
1860 setArg(
"-avastalevotethreshold",
1862 setArg(
"-avastalevotefactor",
"2");
1864 setArg(
"-avalanchestakingpreconsensus",
"0");
1866 const std::vector<std::tuple<int, int>> testCases = {
1873 m_node.avalanche = Processor::MakeProcessor(
1882 const uint32_t invType = provider.invType;
1884 const auto item = provider.buildVoteItem();
1885 const auto itemid = provider.getVoteItemId(item);
1888 auto avanodes = ConnectNodes();
1889 int nextNodeIndex = 0;
1891 std::vector<avalanche::VoteItemUpdate> updates;
1892 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
1895 auto invs = getInvsForNextPoll();
1902 auto registerNewVote = [&](
const Response &resp) {
1904 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1905 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1909 for (
int i = 0; i < numYesVotes; i++) {
1911 registerNewVote(next(resp));
1914 i >= 6 ? i - 5 : 0);
1919 for (
int i = 0; i < numNeutralVotes; i++) {
1921 registerNewVote(next(resp));
1926 invs = getInvsForNextPoll();
1933 registerNewVote(next(resp));
1935 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
1936 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
1939 invs = getInvsForNextPoll();
1945 BlockProvider provider(
this);
1949 std::vector<CBlockIndex *> blockIndexes;
1953 blockIndexes.push_back(pindex);
1956 auto invs = getInvsForNextPoll();
1970 std::vector<Vote> votes;
1973 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
1974 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
1977 auto avanodes = ConnectNodes();
1978 int nextNodeIndex = 0;
1980 std::vector<avalanche::VoteItemUpdate> updates;
1981 auto registerNewVote = [&]() {
1982 Response resp = {getRound(), 0, votes};
1984 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1985 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1991 bool eleventhBlockFinalized =
false;
1992 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
1995 for (
auto &update : updates) {
1996 if (update.getStatus() == VoteStatus::Finalized &&
1997 provider.fromAnyVoteItem(update.getVoteItem())
1998 ->GetBlockHash() == eleventhBlockHash) {
1999 eleventhBlockFinalized =
true;
2010 clearInvsNotWorthPolling();
2011 invs = getInvsForNextPoll();
2013 for (
size_t i = 0; i < 10; i++) {
2028 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2030 activeChainstate.InvalidateBlock(state, tip);
2033 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2036 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2044 activeChainstate.ResetBlockFailureFlags(tip);
2046 activeChainstate.ActivateBestChain(state);
2050 clearInvsNotWorthPolling();
2051 invs = getInvsForNextPoll();
2058 for (
auto &inv : invs) {
2059 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2062 bool tipFinalized =
false;
2063 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2066 for (
auto &update : updates) {
2067 if (update.getStatus() == VoteStatus::Finalized &&
2068 provider.fromAnyVoteItem(update.getVoteItem())
2069 ->GetBlockHash() == tiphash) {
2070 tipFinalized =
true;
2079 clearInvsNotWorthPolling();
2080 invs = getInvsForNextPoll();
2088 BlockHash alttiphash = alttip->GetBlockHash();
2089 votes = {{1, alttiphash}};
2091 bool alttipInvalidated =
false;
2092 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2095 for (
auto &update : updates) {
2096 if (update.getStatus() == VoteStatus::Invalid &&
2097 provider.fromAnyVoteItem(update.getVoteItem())
2098 ->GetBlockHash() == alttiphash) {
2099 alttipInvalidated =
true;
2104 invs = getInvsForNextPoll();
2115 const int numberElementsEachType = 100;
2118 std::vector<ProofRef> proofs;
2119 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2123 proofs.emplace_back(std::move(proof));
2125 Shuffle(proofs.begin(), proofs.end(), rng);
2127 std::vector<CBlockIndex> indexes;
2128 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2131 indexes.emplace_back(std::move(index));
2133 Shuffle(indexes.begin(), indexes.end(), rng);
2135 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2136 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2142 for (
size_t i = 0; i < numberElementsEachType; i++) {
2144 const size_t firstType = rng.
randrange(numTypes);
2146 for (
size_t j = 0; j < numTypes; j++) {
2147 switch ((firstType + j) % numTypes) {
2150 writeView->insert(std::make_pair(
2151 std::get<0>(allItems)[i],
VoteRecord(
true)));
2155 writeView->insert(std::make_pair(
2156 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2167 auto readView = voteMap.getReadView();
2168 auto it = readView.begin();
2171 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2172 for (
size_t i = 0; i < numberElementsEachType; i++) {
2173 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2175 uint32_t currentScore =
2176 std::get<const ProofRef>(it->first)->getScore();
2177 BOOST_CHECK_LT(currentScore, lastScore);
2178 lastScore = currentScore;
2186 for (
size_t i = 0; i < numberElementsEachType; i++) {
2187 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2190 std::get<const CBlockIndex *>(it->first)->nChainWork;
2192 lastWork = currentWork;
2205 const auto block = std::make_shared<const CBlock>(
2206 this->CreateBlock({}, CScript(), chainstate));
2233 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
2246 auto now = GetTime<std::chrono::seconds>();
2252 std::vector<CScript> winners;
2255 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2260 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2265 prevBlock.
nTime = now.count();
2270 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2273 size_t numProofs = 10;
2274 std::vector<ProofRef> proofs;
2275 proofs.reserve(numProofs);
2276 for (
size_t i = 0; i < numProofs; i++) {
2280 auto proof = GetProof(payoutScript);
2287 return pm.setFinalized(peer.peerid);
2291 proofs.emplace_back(std::move(proof));
2299 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2302 auto winnerExists = [&](
const CScript &expectedWinner) {
2303 const std::string winnerString =
FormatScript(expectedWinner);
2305 for (
const ProofRef &proof : proofs) {
2316 prevBlock.
nTime = now.count();
2321 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2327 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2333 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2337 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2342 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2346 m_node.avalanche->cleanupStakingRewards(101);
2350 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2354 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2360 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2364 m_node.avalanche->cleanupStakingRewards(200);
2368 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2370 !
m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2382 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2388 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2396 auto localProof = buildProof(outpoint, 1, 100);
2399 setArg(
"-avaproof", localProof->ToHex());
2400 setArg(
"-avalancheconflictingproofcooldown",
"0");
2401 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2402 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2406 m_node.avalanche = Processor::MakeProcessor(
2411 localProof->getId());
2413 auto checkLocalProofState = [&](
const bool boundToPeer,
2418 return pm.isBoundToPeer(localProof->getId());
2421 BOOST_CHECK_MESSAGE(
2422 m_node.avalanche->getLocalProofRegistrationState().GetResult() ==
2424 m_node.avalanche->getLocalProofRegistrationState().ToString());
2431 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2435 AvalancheTest::setLocalProofShareable(*
m_node.avalanche,
true);
2437 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2438 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2442 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2443 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2447 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2451 auto conflictingProof = buildProof(outpoint, 2, 100);
2457 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2458 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2462 setArg(
"-avalancheconflictingproofcooldown",
"0");
2463 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2483 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2490 auto proof = buildProof(outpoint, 1);
2509 AvalancheTest::addProofToRecentfinalized(*
m_node.avalanche, proof->
getId());
2516 return peer.hasFinalized;
2523 auto betterProof = buildProof(outpoint, 2);
2546 m_node.avalanche = Processor::MakeProcessor(
2552 auto now = GetTime<std::chrono::seconds>();
2555 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
true);
2563 const ProofId proofid1 = proof1->getId();
2568 const ProofId proofid2 = proof2->getId();
2579 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2581 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2587 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2592 for (
NodeId n = 0; n < 8; n++) {
2597 return pm.setFinalized(peer.peerid);
2606 CBlock block = CreateAndProcessBlock({}, CScript());
2609 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2610 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2616 std::vector<CScript> winners;
2620 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2625 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2629 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2631 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2637 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2643 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2651 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2654 m_node.avalanche->getStakeContenderStatus(contender1_block1), -1);
2656 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2659 m_node.avalanche->getStakeContenderStatus(contender2_block1), -1);
2661 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2664 m_node.avalanche->setStakingRewardWinners(
2665 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2670 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2673 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2676 m_node.avalanche->withPeerManager(
2682 const ProofId proofid3 = proof3->getId();
2685 for (
NodeId n = 0; n < 8; n++) {
2691 block = CreateAndProcessBlock({}, CScript());
2694 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2695 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2699 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2703 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2705 m_node.avalanche->getStakeContenderStatus(contender2_block2), -1);
2712 m_node.avalanche->getStakeContenderStatus(contender1_block3), -1);
2716 m_node.avalanche->getStakeContenderStatus(contender2_block3), -1);
2719 m_node.avalanche->withPeerManager(
2723 size_t numProofs = 8;
2724 std::vector<ProofRef> proofs;
2725 proofs.reserve(numProofs);
2726 for (
size_t i = 0; i < numProofs; i++) {
2735 return pm.setFinalized(peer.peerid);
2738 proofs.emplace_back(std::move(proof));
2743 const ProofId proofid = proofs[0]->getId();
2744 for (
NodeId n = 0; n < 8; n++) {
2754 std::vector<CScript> winners;
2755 for (
int attempt = 0; attempt < 10; attempt++) {
2757 block = CreateAndProcessBlock({}, CScript());
2760 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2761 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2767 chaintip->GetBlockHash(), winners));
2768 if (winners.size() == 8) {
2776 size_t numAccepted = 0;
2777 for (
const auto &proof : proofs) {
2781 if (
m_node.avalanche->getStakeContenderStatus(contender) == 0) {
2783 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2791 block = CreateAndProcessBlock({}, CScript());
2794 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2799 m_node.avalanche->withPeerManager(
2801 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2810 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2811 bestproof->getPayoutScript()) == winners.end());
2818 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2829 block = CreateAndProcessBlock({}, CScript());
2832 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2833 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2834 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
2841 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2855 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2856 bestproof->getPayoutScript()) == winners.end());
2864 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2875 auto now = GetTime<std::chrono::seconds>();
2879 auto localWinnerProof =
2881 ProofId localWinnerProofId = localWinnerProof->getId();
2883 localWinnerProof->getId());
2892 for (
NodeId n = 0; n < 8; n++) {
2893 pm.
addNode(n, localWinnerProofId,
2897 return pm.setFinalized(peer.peerid);
2904 chaintip->
nTime = now.count();
2910 std::vector<ProofRef> acceptedContenderProofs;
2911 acceptedContenderProofs.push_back(localWinnerProof);
2918 for (
size_t numContenders = 2;
2922 m_node.avalanche->withPeerManager(
2928 if (rank <= bestRank) {
2930 acceptedContenderProofs.push_back(proof);
2931 const size_t numAccepted =
2933 acceptedContenderProofs.size());
2934 std::sort(acceptedContenderProofs.begin(),
2935 acceptedContenderProofs.begin() + numAccepted,
2937 const ProofId leftProofId = left->getId();
2938 const ProofId rightProofId = right->getId();
2939 const StakeContenderId leftContenderId(chaintipHash,
2941 const StakeContenderId rightContenderId(chaintipHash,
2943 return RewardRankComparator()(
2945 leftContenderId.ComputeProofRewardRank(
2946 MIN_VALID_PROOF_SCORE),
2947 leftProofId, rightContenderId,
2948 rightContenderId.ComputeProofRewardRank(
2949 MIN_VALID_PROOF_SCORE),
2954 std::vector<StakeContenderId> pollableContenders;
2955 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
2956 *
m_node.avalanche, chaintip, pollableContenders));
2958 pollableContenders.size(),
2963 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
2967 chaintipHash, acceptedContenderProofs[i]->getId());
2969 std::find(pollableContenders.begin(), pollableContenders.end(),
2970 acceptedContenderId) != pollableContenders.end());
2972 m_node.avalanche->getStakeContenderStatus(acceptedContenderId),
2977 std::set<StakeContenderId> unacceptedContenderIds(
2978 pollableContenders.begin(), pollableContenders.end());
2979 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
2981 chaintipHash, acceptedContenderProof->getId());
2982 unacceptedContenderIds.erase(acceptedContenderId);
2985 for (
auto cid : unacceptedContenderIds) {
2992 m_node.avalanche->getStakeContenderStatus(localWinnerContenderId),
2997BOOST_AUTO_TEST_SUITE_END()
static constexpr Amount SATOSHI
static constexpr Amount COIN
uint256 ArithToUint256(const arith_uint256 &a)
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
A CService with information about it as peer.
The block chain is a tree shaped structure starting with the genesis block at the root,...
CBlockIndex * pprev
pointer to the index of the predecessor of this block
arith_uint256 nChainWork
(memory only) Total amount of work (expected number of hashes) in the chain up to and including this ...
const BlockHash * phashBlock
pointer to the hash of the block, if any.
BlockHash GetBlockHash() const
int nHeight
height of the entry in the chain. The genesis block has height 0
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or nullptr if none.
CCoinsView that adds a memory cache for transactions to another CCoinsView.
void AddCoin(const COutPoint &outpoint, Coin coin, bool possible_overwrite)
Add a coin.
bool SpendCoin(const COutPoint &outpoint, Coin *moveto=nullptr)
Spend a coin.
An encapsulated secp256k1 private key.
static CKey MakeCompressedKey()
Produce a valid compressed key.
CPubKey GetPubKey() const
Compute the public key from a private key.
A mutable version of CTransaction.
std::vector< CTxOut > vout
Information about a peer.
Simple class for background tasks that should be run periodically or once "after a while".
void serviceQueue() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Services the queue 'forever'.
size_t getQueueInfo(std::chrono::steady_clock::time_point &first, std::chrono::steady_clock::time_point &last) const EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Returns number of tasks waiting to be serviced, and first and last task times.
void StopWhenDrained() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Tell any threads running serviceQueue to stop when there is no work left to be done.
A combination of a network address (CNetAddr) and a (TCP) port.
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
void removeRecursive(const CTransaction &tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs)
bool exists(const TxId &txid) const
void check(const CCoinsViewCache &active_coins_tip, int64_t spendheight) const EXCLUSIVE_LOCKS_REQUIRED(void addUnchecked(CTxMemPoolEntryRef entry) EXCLUSIVE_LOCKS_REQUIRED(cs
If sanity-checking is turned on, check makes sure the pool is consistent (does not contain two transa...
An output of a transaction.
Chainstate stores and provides an API to update our local knowledge of the current best chain.
bool ActivateBestChain(BlockValidationState &state, std::shared_ptr< const CBlock > pblock=nullptr, avalanche::Processor *const avalanche=nullptr) EXCLUSIVE_LOCKS_REQUIRED(!m_chainstate_mutex
Find the best known block, and make it the tip of the block chain.
CChain m_chain
The current chain of blockheaders we consult and build on.
CCoinsViewCache & CoinsTip() EXCLUSIVE_LOCKS_REQUIRED(
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
SnapshotCompletionResult MaybeCompleteSnapshotValidation() EXCLUSIVE_LOCKS_REQUIRED(const CBlockIndex *GetSnapshotBaseBlock() const EXCLUSIVE_LOCKS_REQUIRED(Chainstate ActiveChainstate)() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
RecursiveMutex & GetMutex() const LOCK_RETURNED(
Alias for cs_main.
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
bool AcceptBlock(const std::shared_ptr< const CBlock > &pblock, BlockValidationState &state, bool fRequested, const FlatFilePos *dbp, bool *fNewBlock, bool min_pow_checked) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
Sufficiently validate a block for disk storage (and store on disk).
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
ReadView getReadView() const
I randrange(I range) noexcept
Generate a random integer in the range [0..range), with range > 0.
256-bit unsigned big integer.
bool removeNode(NodeId nodeid)
uint32_t getConnectedPeersScore() const
bool isDangling(const ProofId &proofid) const
bool addNode(NodeId nodeid, const ProofId &proofid, size_t max_elements)
Node API.
bool exists(const ProofId &proofid) const
Return true if the (valid) proof exists, but only for non-dangling proofs.
bool forPeer(const ProofId &proofid, Callable &&func) const
uint32_t getTotalPeersScore() const
std::unordered_set< ProofRef, SaltedProofHasher > updatedBlockTip()
Update the peer set when a new block is connected.
bool isBoundToPeer(const ProofId &proofid) const
bool saveRemoteProof(const ProofId &proofid, const NodeId nodeid, const bool present)
bool isImmature(const ProofId &proofid) const
bool rejectProof(const ProofId &proofid, RejectionMode mode=RejectionMode::DEFAULT)
void addStakeContender(const ProofRef &proof)
bool isInConflictingPool(const ProofId &proofid) const
void cleanupDanglingProofs(std::unordered_set< ProofRef, SaltedProofHasher > ®isteredProofs)
bool registerProof(const ProofRef &proof, ProofRegistrationState ®istrationState, RegistrationMode mode=RegistrationMode::DEFAULT)
Mutex cs_finalizedItems
Rolling bloom filter to track recently finalized inventory items of any type.
bool setContenderStatusForLocalWinners(const CBlockIndex *pindex, std::vector< StakeContenderId > &pollableContenders) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Helper to set the vote status for local winners in the contender cache.
std::atomic< uint64_t > round
Keep track of peers and queries sent.
void runEventLoop() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
void updatedBlockTip() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
RWCollection< VoteMap > voteRecords
Items to run avalanche on.
uint32_t minQuorumScore
Quorum management.
std::atomic< bool > m_canShareLocalProof
std::vector< CInv > getInvsForNextPoll(RWCollection< VoteMap >::ReadView &voteRecordsReadView, size_t max_elements, bool forPoll=true) const
std::atomic< int64_t > avaproofsNodeCounter
std::atomic_bool m_stakingPreConsensus
Mutex cs_peerManager
Keep track of the peers and associated infos.
void clearInvsNotWorthPolling() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
double minQuorumConnectedScoreRatio
bool addUTXO(COutPoint utxo, Amount amount, uint32_t height, bool is_coinbase, CKey key)
const CScript & getPayoutScript() const
const ProofId & getId() const
const std::vector< SignedStake > & getStakes() const
uint32_t getCooldown() const
const std::vector< Vote > & GetVotes() const
uint64_t getRound() const
const AnyVoteItem & getVoteItem() const
const VoteStatus & getStatus() const
static constexpr unsigned int size()
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
static const uint256 ZERO
@ OUTBOUND_FULL_RELAY
These are the default connections that we use to connect with the network.
std::string FormatScript(const CScript &script)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
std::string EncodeSecret(const CKey &key)
static constexpr Amount PROOF_DUST_THRESHOLD
Minimum amount per utxo.
std::variant< const ProofRef, const CBlockIndex *, const StakeContenderId, const CTransactionRef > AnyVoteItem
const CScript UNSPENDABLE_ECREG_PAYOUT_SCRIPT
ProofRef buildRandomProof(Chainstate &active_chainstate, uint32_t score, int height, const CKey &masterKey)
constexpr uint32_t MIN_VALID_PROOF_SCORE
std::string ToString(const T &t)
Locale-independent version of std::to_string.
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
#define BOOST_CHECK_EQUAL(v1, v2)
#define BOOST_CHECK(expr)
static CTransactionRef MakeTransactionRef()
std::shared_ptr< const CTransaction > CTransactionRef
static constexpr size_t DEFAULT_AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
static constexpr size_t AVALANCHE_CONTENDER_MAX_POLLABLE
Maximum number of stake contenders to poll for, leaving room for polling blocks and proofs in the sam...
static constexpr uint32_t AVALANCHE_FINALIZED_ITEMS_FILTER_NUM_ELEMENTS
The size of the finalized items filter.
BOOST_AUTO_TEST_CASE_TEMPLATE(voteitemupdate, P, VoteItemProviders)
BOOST_AUTO_TEST_CASE(quorum_diversity)
boost::mpl::list< BlockProvider, ProofProvider, StakeContenderProvider, TxProvider > VoteItemProviders
boost::mpl::list< StakeContenderProvider > Uint256VoteItemProviders
boost::mpl::list< BlockProvider, ProofProvider, TxProvider > NullableVoteItemProviders
static bool HasAllDesirableServiceFlags(ServiceFlags services)
A shortcut for (services & GetDesirableServiceFlags(services)) == GetDesirableServiceFlags(services),...
@ MSG_AVA_STAKE_CONTENDER
ServiceFlags
nServices flags.
static const int PROTOCOL_VERSION
network protocol versioning
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
uint256 GetRandHash() noexcept
========== CONVENIENCE FUNCTIONS FOR COMMONLY USED RANDOMNESS ==========
reverse_range< T > reverse_iterate(T &x)
static uint16_t GetDefaultPort()
static std::string ToString(const CService &ip)
CScript GetScriptForRawPubKey(const CPubKey &pubKey)
Generate a P2PK script for the given pubkey.
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
A BlockHash is a unqiue identifier for a block.
static const Currency & get()
A TxId is the identifier of a transaction.
Compare proofs by score, then by id in case of equality.
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
double ComputeProofRewardRank(uint32_t proofScore) const
To make sure the selection is properly weighted according to the proof score, we normalize the conten...
TestVoteRecord(uint16_t conf)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
void UninterruptibleSleep(const std::chrono::microseconds &n)
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
@ CONFLICT
Removed for conflict with in-block transaction.
void SyncWithValidationInterfaceQueue()
This is a synonym for the following, which asserts certain locks are not held: std::promise<void> pro...
static constexpr int AVALANCHE_MAX_INFLIGHT_POLL
How many inflight requests can exist for one item.
static constexpr uint32_t AVALANCHE_VOTE_STALE_MIN_THRESHOLD
Lowest configurable staleness threshold (finalization score + necessary votes to increase confidence ...
static constexpr int AVALANCHE_FINALIZATION_SCORE
Finalization score.