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>
41 struct AvalancheTest {
44 static std::vector<CInv> getInvsForNextPoll(
Processor &p) {
50 return p.peerManager->selectNode());
55 static uint32_t getMinQuorumScore(
const Processor &p) {
59 static double getMinQuorumConnectedScoreRatio(
const Processor &p) {
63 static void clearavaproofsNodeCounter(
Processor &p) {
70 std::make_pair(item, voteRecord));
77 static void setFinalizationTip(
Processor &p,
80 p.finalizationTip = pindex;
83 static void setLocalProofShareable(
Processor &p,
bool shareable) {
89 static void addProofToRecentfinalized(
Processor &p,
92 return p.finalizedItems.insert(proofid));
95 static bool setContenderStatusForLocalWinners(
97 std::vector<StakeContenderId> &pollableContenders) {
102 static void setStakingPreconsensus(
Processor &p,
bool enabled) {
122struct AvalancheProcessorTestingSetup :
public AvalancheTestChain100Setup {
123 AvalancheProcessorTestingSetup() : AvalancheTestChain100Setup() {
124 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
false);
132 new CNode(
id++,
nullptr, addr,
139 node->m_has_all_wanted_services =
143 node->fSuccessfullyConnected =
true;
145 m_connman->AddTestNode(*
node);
154 const uint32_t height = 100;
163 BOOST_CHECK(pb.addUTXO(outpoint, amount, height,
false, key));
168 return m_node.avalanche->withPeerManager(
170 return pm.
addNode(nodeid, proofid);
174 bool addNode(
NodeId nodeid) {
175 auto proof = GetProof();
176 return m_node.avalanche->withPeerManager(
179 pm.
addNode(nodeid, proof->getId());
183 std::array<CNode *, 8> ConnectNodes() {
184 auto proof = GetProof();
187 return pm.registerProof(proof);
189 const ProofId &proofid = proof->getId();
191 std::array<CNode *, 8> nodes;
192 for (
CNode *&n : nodes) {
200 void runEventLoop() { AvalancheTest::runEventLoop(*
m_node.avalanche); }
202 NodeId getSuitableNodeToQuery() {
203 return AvalancheTest::getSuitableNodeToQuery(*
m_node.avalanche);
206 std::vector<CInv> getInvsForNextPoll() {
207 return AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
210 uint64_t getRound()
const {
211 return AvalancheTest::getRound(*
m_node.avalanche);
215 std::vector<avalanche::VoteItemUpdate> &updates,
216 std::string &error) {
223 std::vector<avalanche::VoteItemUpdate> &updates) {
231 return m_node.avalanche->addToReconcile(item);
235struct BlockProvider {
236 AvalancheProcessorTestingSetup *fixture;
239 BlockProvider(AvalancheProcessorTestingSetup *_fixture)
240 : fixture(_fixture) {}
243 CBlock block = fixture->CreateAndProcessBlock({}, CScript());
247 return Assert(fixture->m_node.chainman)
248 ->m_blockman.LookupBlockIndex(blockHash);
255 std::vector<Vote> buildVotesForItems(uint32_t error,
256 std::vector<CBlockIndex *> &&items) {
257 size_t numItems = items.
size();
259 std::vector<Vote> votes;
260 votes.reserve(numItems);
265 votes.emplace_back(error, item->GetBlockHash());
273 pindex->nStatus = pindex->nStatus.withFailed();
277 return std::get<const CBlockIndex *>(item);
281struct ProofProvider {
282 AvalancheProcessorTestingSetup *fixture;
285 ProofProvider(AvalancheProcessorTestingSetup *_fixture)
286 : fixture(_fixture) {}
289 ProofRef proof = fixture->GetProof();
290 fixture->m_node.avalanche->withPeerManager(
298 return proof->
getId();
301 std::vector<Vote> buildVotesForItems(uint32_t error,
302 std::vector<ProofRef> &&items) {
303 size_t numItems = items.
size();
305 std::vector<Vote> votes;
306 votes.reserve(numItems);
310 for (
auto &item : items) {
311 votes.emplace_back(error, item->getId());
317 void invalidateItem(
const ProofRef &proof) {
318 fixture->m_node.avalanche->withPeerManager(
327 return std::get<const ProofRef>(item);
331struct StakeContenderProvider {
332 AvalancheProcessorTestingSetup *fixture;
334 std::vector<avalanche::VoteItemUpdate> updates;
337 StakeContenderProvider(AvalancheProcessorTestingSetup *_fixture)
338 : fixture(_fixture) {}
345 std::vector<CScript> winners;
346 if (!fixture->m_node.avalanche->getStakingRewardWinners(
350 const ProofRef proofWinner = fixture->GetProof();
352 fixture->m_node.avalanche->setStakingRewardWinners(chaintip,
357 const ProofRef proof = fixture->GetProof();
361 fixture->m_node.avalanche->withPeerManager(
368 fixture->m_node.avalanche->acceptStakeContender(contenderId);
370 BOOST_CHECK(fixture->m_node.avalanche->getStakeContenderStatus(
380 buildVotesForItems(uint32_t error, std::vector<StakeContenderId> &&items) {
381 size_t numItems = items.
size();
383 std::vector<Vote> votes;
384 votes.reserve(numItems);
387 std::sort(items.begin(), items.end(),
391 for (
auto &item : items) {
392 votes.emplace_back(error, item);
399 fixture->m_node.avalanche->rejectStakeContender(contenderId);
407 AvalancheTest::removeVoteRecord(*(fixture->m_node.avalanche),
412 return std::get<const StakeContenderId>(item);
417 AvalancheProcessorTestingSetup *fixture;
419 std::vector<avalanche::VoteItemUpdate> updates;
422 TxProvider(AvalancheProcessorTestingSetup *_fixture) : fixture(_fixture) {}
432 TestMemPoolEntryHelper mempoolEntryHelper;
433 auto entry = mempoolEntryHelper.Fee(1000 *
SATOSHI).FromTx(tx);
449 std::vector<Vote> buildVotesForItems(uint32_t error,
450 std::vector<CTransactionRef> &&items) {
451 size_t numItems = items.
size();
453 std::vector<Vote> votes;
454 votes.reserve(numItems);
457 std::sort(items.begin(), items.end(),
459 return lhs->GetId() < rhs->GetId();
461 for (
auto &item : items) {
462 votes.emplace_back(error, item->GetId());
478 return std::get<const CTransactionRef>(item);
484BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheProcessorTestingSetup)
488 StakeContenderProvider, TxProvider>;
490 boost::mpl::list<BlockProvider, ProofProvider, TxProvider>;
499 std::set<VoteStatus> status{
500 VoteStatus::Invalid, VoteStatus::Rejected, VoteStatus::Accepted,
501 VoteStatus::Finalized, VoteStatus::Stale,
504 auto item = provider.buildVoteItem();
506 for (
auto s : status) {
529 auto item = provider.buildVoteItem();
530 auto itemid = provider.getVoteItemId(item);
539 auto avanodes = ConnectNodes();
541 int nextNodeIndex = 0;
542 std::vector<avalanche::VoteItemUpdate> updates;
543 auto registerNewVote = [&](
const Response &resp) {
545 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
550 auto finalize = [&](
const auto finalizeItemId) {
551 Response resp = {getRound(), 0, {
Vote(0, finalizeItemId)}};
553 registerNewVote(next(resp));
554 if (updates.size() > 0) {
559 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
560 m_node.avalanche->setRecentlyFinalized(finalizeItemId);
567 auto finalizeNewItem = [&]() {
568 auto anotherItem = provider.buildVoteItem();
570 auto anotherItemId = provider.getVoteItemId(anotherItem);
573 AvalancheTest::addVoteRecord(*
m_node.avalanche, anotherVoteItem,
575 finalize(anotherItemId);
595 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
608 auto item =
decltype(provider.buildVoteItem())();
615 item = provider.buildVoteItem();
626 auto itemZero =
decltype(provider.buildVoteItem())();
639 auto item = provider.buildVoteItem();
649 const uint32_t invType = provider.invType;
651 auto item = provider.buildVoteItem();
652 auto itemid = provider.getVoteItemId(item);
655 auto avanodes = ConnectNodes();
663 auto invs = getInvsForNextPoll();
671 int nextNodeIndex = 0;
672 std::vector<avalanche::VoteItemUpdate> updates;
673 auto registerNewVote = [&](
const Response &resp) {
675 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
681 for (
int i = 0; i < 6; i++) {
682 registerNewVote(next(resp));
689 resp = {getRound(), 0, {
Vote(-1, itemid)}};
690 registerNewVote(next(resp));
695 resp = {getRound(), 0, {
Vote(0, itemid)}};
696 for (
int i = 1; i < 7; i++) {
697 registerNewVote(next(resp));
704 resp = {getRound(), 0, {
Vote(-1, itemid)}};
705 registerNewVote(next(resp));
709 registerNewVote(next(resp));
714 resp = {getRound(), 0, {
Vote(0, itemid)}};
715 for (
int i = 2; i < 8; i++) {
716 registerNewVote(next(resp));
724 registerNewVote(next(resp));
731 invs = getInvsForNextPoll();
737 registerNewVote(next(resp));
739 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
740 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
743 invs = getInvsForNextPoll();
747 item = provider.buildVoteItem();
748 itemid = provider.getVoteItemId(item);
752 invs = getInvsForNextPoll();
757 resp = {getRound(), 0, {
Vote(1, itemid)}};
758 for (
int i = 0; i < 6; i++) {
759 registerNewVote(next(resp));
765 registerNewVote(next(resp));
768 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
769 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
773 registerNewVote(next(resp));
779 invs = getInvsForNextPoll();
785 registerNewVote(next(resp));
788 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
789 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
792 invs = getInvsForNextPoll();
798 const uint32_t invType = provider.invType;
800 auto itemA = provider.buildVoteItem();
801 auto itemidA = provider.getVoteItemId(itemA);
803 auto itemB = provider.buildVoteItem();
804 auto itemidB = provider.getVoteItemId(itemB);
807 auto avanodes = ConnectNodes();
815 auto invs = getInvsForNextPoll();
820 uint64_t round = getRound();
822 std::vector<avalanche::VoteItemUpdate> updates;
824 {round, 0, {
Vote(0, itemidA)}}, updates));
828 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
831 invs = getInvsForNextPoll();
835 for (
size_t i = 0; i < invs.size(); i++) {
841 for (
int i = 0; i < 4; i++) {
842 NodeId nodeid = getSuitableNodeToQuery();
844 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
850 NodeId nodeid = getSuitableNodeToQuery();
852 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
858 NodeId firstNodeid = getSuitableNodeToQuery();
860 NodeId secondNodeid = getSuitableNodeToQuery();
866 BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates));
868 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemA);
869 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
872 invs = getInvsForNextPoll();
878 BOOST_CHECK(registerVotes(secondNodeid, resp, updates));
880 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemB);
881 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
884 invs = getInvsForNextPoll();
890 const uint32_t invType = provider.invType;
892 auto item = provider.buildVoteItem();
893 auto itemid = provider.getVoteItemId(item);
900 std::set<NodeId> avanodeIds;
901 auto avanodes = ConnectNodes();
902 for (
auto avanode : avanodes) {
904 avanodeIds.insert(avanode->GetId());
907 auto getSelectedAvanodeId = [&]() {
908 NodeId avanodeid = getSuitableNodeToQuery();
909 BOOST_CHECK(avanodeIds.find(avanodeid) != avanodeIds.end());
914 NodeId avanodeid = getSelectedAvanodeId();
918 auto invs = getInvsForNextPoll();
923 std::set<NodeId> unselectedNodeids = avanodeIds;
924 unselectedNodeids.erase(avanodeid);
925 const size_t remainingNodeIds = unselectedNodeids.size();
927 uint64_t round = getRound();
928 for (
size_t i = 0; i < remainingNodeIds; i++) {
933 NodeId nodeid = getSuitableNodeToQuery();
934 BOOST_CHECK(unselectedNodeids.find(nodeid) != avanodeIds.end());
935 unselectedNodeids.erase(nodeid);
945 std::vector<avalanche::VoteItemUpdate> updates;
946 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
953 auto checkRegisterVotesError = [&](
NodeId nodeid,
955 const std::string &expectedError) {
963 checkRegisterVotesError(avanodeid, next(resp),
"unexpected-ava-response");
972 resp = {round, 0, {
Vote(0, itemid),
Vote(0, itemid)}};
974 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
978 resp = {getRound(), 0, {}};
980 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
984 resp = {getRound(), 0, {
Vote()}};
986 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
993 invs = getInvsForNextPoll();
996 item = provider.buildVoteItem();
997 itemid = provider.getVoteItemId(item);
1000 invs = getInvsForNextPoll();
1004 uint64_t queryRound = getRound();
1007 resp = {queryRound + 1, 0, {
Vote()}};
1008 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1010 resp = {queryRound - 1, 0, {
Vote()}};
1011 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1015 resp = {queryRound, 0, {
Vote(0, itemid)}};
1016 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1019 resp = {queryRound, 0, {
Vote(0, itemid)}};
1020 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1025 const auto item2 = provider.buildVoteItem();
1028 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1029 resp = {getRound(), 0, {votes[1], votes[0]}};
1031 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1035 resp = {getRound(), 0, votes};
1037 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1044 const uint32_t invType = provider.invType;
1046 auto itemA = provider.buildVoteItem();
1047 auto itemB = provider.buildVoteItem();
1049 auto avanodes = ConnectNodes();
1050 int nextNodeIndex = 0;
1053 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1059 auto invs = getInvsForNextPoll();
1061 for (
size_t i = 0; i < invs.size(); i++) {
1067 provider.invalidateItem(itemB);
1069 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1070 std::vector<avalanche::VoteItemUpdate> updates;
1073 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1074 goodResp, updates));
1078 invs = getInvsForNextPoll();
1081 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1084 Response badResp{getRound(), 0, votes};
1088 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1089 badResp, updates, error));
1093 votes = provider.buildVotesForItems(1, {itemA});
1094 auto registerNewVote = [&]() {
1095 Response resp = {getRound(), 0, votes};
1097 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1098 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1100 for (
size_t i = 0; i < 4000; i++) {
1102 if (updates.size() > 0 &&
1103 updates[0].getStatus() == VoteStatus::Invalid) {
1109 invs = getInvsForNextPoll();
1113 badResp =
Response(getRound(), 0, votes);
1116 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1117 badResp, updates, error));
1121BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1126 auto queryTimeDuration = std::chrono::milliseconds(10);
1127 setArg(
"-avatimeout",
ToString(queryTimeDuration.count()));
1129 setArg(
"-avalanchestakingpreconsensus",
"0");
1132 m_node.avalanche = Processor::MakeProcessor(
1136 const auto item = provider.buildVoteItem();
1137 const auto itemid = provider.getVoteItemId(item);
1147 for (
int i = 0; i < 10; i++) {
1149 avanodeid = getSuitableNodeToQuery();
1151 auto start = Now<SteadyMilliseconds>();
1155 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1158 std::vector<avalanche::VoteItemUpdate> updates;
1159 bool ret = registerVotes(avanodeid, next(resp), updates);
1160 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1171 avanodeid = getSuitableNodeToQuery();
1175 std::this_thread::sleep_for(queryTimeDuration);
1177 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1183 const uint32_t invType = provider.invType;
1186 auto proof = GetProof();
1190 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1191 for (
auto &n : nodes) {
1197 const auto item = provider.buildVoteItem();
1198 const auto itemid = provider.getVoteItemId(item);
1202 std::map<NodeId, uint64_t> node_round_map;
1204 NodeId nodeid = getSuitableNodeToQuery();
1205 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1206 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1207 auto invs = getInvsForNextPoll();
1215 auto suitablenodeid = getSuitableNodeToQuery();
1217 auto invs = getInvsForNextPoll();
1223 auto it = node_round_map.begin();
1225 std::vector<avalanche::VoteItemUpdate> updates;
1226 BOOST_CHECK(registerVotes(it->first, resp, updates));
1227 node_round_map.erase(it);
1229 invs = getInvsForNextPoll();
1236 std::vector<VoteItemUpdate> updates;
1238 CBlock block = CreateAndProcessBlock({}, CScript());
1244 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1248 auto avanodes = ConnectNodes();
1257 uint64_t round = getRound();
1261 for (
size_t i = 0; i < avanodes.size(); i++) {
1263 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1267 const NodeId firstNodeId = getSuitableNodeToQuery();
1268 std::map<NodeId, uint64_t> node_round_map;
1270 for (
size_t i = 0; i < avanodes.size(); i++) {
1271 NodeId nodeid = getSuitableNodeToQuery();
1272 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1273 node_round_map[nodeid] = getRound();
1279 auto confidence =
m_node.avalanche->getConfidence(pindex);
1280 BOOST_REQUIRE(confidence > 0);
1282 for (
auto &[nodeid, r] : node_round_map) {
1283 if (nodeid == firstNodeId) {
1290 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1295 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1302 CBlock block = CreateAndProcessBlock({}, CScript());
1308 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1315 std::chrono::steady_clock::time_point start,
stop;
1325 auto avanodes = ConnectNodes();
1328 NodeId nodeid = getSuitableNodeToQuery();
1329 BOOST_CHECK_NE(nodeid,
NO_NODE);
1332 uint64_t queryRound = getRound();
1336 for (
int i = 0; i < 60 * 1000; i++) {
1340 if (getRound() == queryRound + avanodes.size()) {
1349 uint64_t responseRound = getRound();
1350 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1352 std::vector<VoteItemUpdate> updates;
1354 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1357 for (
int i = 0; i < 10000; i++) {
1360 if (getRound() != responseRound) {
1361 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1380 schedulerThread.join();
1385 std::chrono::steady_clock::time_point start,
stop;
1387 std::thread schedulerThread;
1397 m_node.avalanche.reset();
1404 schedulerThread.join();
1411 auto addProofToReconcile = [&](uint32_t proofScore) {
1421 auto proof = addProofToReconcile(++score);
1423 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1432 for (
size_t i = 0; i < 10; i++) {
1433 auto proof = addProofToReconcile(++score);
1435 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1440 lastProofId = proof->
getId();
1443 for (
size_t i = 0; i < 10; i++) {
1444 auto proof = addProofToReconcile(--score);
1446 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1454 auto proof = addProofToReconcile(--score);
1455 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
1456 for (
auto &inv : invs) {
1457 BOOST_CHECK_NE(inv.hash, proof->
getId());
1463 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1464 setArg(
"-avalancheconflictingproofcooldown",
"0");
1478 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1479 coins.
AddCoin(conflictingOutpoint,
1482 coins.
AddCoin(immatureOutpoint,
1487 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1488 uint32_t height = 10) {
1495 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1496 auto validProof = buildProof(conflictingOutpoint, 2);
1497 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1548 int minStake = 400'000'000;
1549 setArg(
"-avaminquorumstake",
ToString(minStake));
1550 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1554 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1562 setArg(
"-avaproof", localProof->ToHex());
1566 m_node.avalanche = Processor::MakeProcessor(
1573 localProof->getId());
1577 AvalancheTest::getMinQuorumConnectedScoreRatio(*
m_node.avalanche), 0.5);
1599 for (
NodeId id = 0;
id < 8;
id++) {
1617 const int64_t tipTime =
1621 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1622 const int height = 100;
1623 const bool isCoinbase =
false;
1630 height, isCoinbase),
1635 auto proof2 = pb.
build();
1646 pm.
addNode(8, proof2->getId());
1665 m_node.avalanche->withPeerManager(
1676 auto spendProofUtxo = [&](
ProofRef proof) {
1689 for (int64_t i = 0; i < 6; i++) {
1691 CreateAndProcessBlock({}, CScript());
1695 ->GetMedianTimePast(),
1696 proof2->getExpirationTime());
1707 spendProofUtxo(proof1);
1714 spendProofUtxo(
m_node.avalanche->getLocalProof());
1726 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1729 {
"",
"",
"",
false},
1730 {
"-1",
"-1",
"-1",
false},
1733 {
"-1",
"0",
"0",
false},
1734 {
"-0.01",
"0",
"0",
false},
1735 {
"21000000000000.01",
"0",
"0",
false},
1738 {
"0",
"-1",
"0",
false},
1739 {
"0",
"1.1",
"0",
false},
1742 {
"0",
"0",
"-1",
false},
1745 {
"0",
"0",
"0",
true},
1746 {
"0.00",
"0",
"0",
true},
1747 {
"0.01",
"0",
"0",
true},
1748 {
"1",
"0.1",
"0",
true},
1749 {
"10",
"0.5",
"0",
true},
1750 {
"10",
"1",
"0",
true},
1751 {
"21000000000000.00",
"0",
"0",
true},
1752 {
"0",
"0",
"1",
true},
1753 {
"0",
"0",
"100",
true},
1758 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1760 setArg(
"-avaminquorumstake", stake);
1761 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1762 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1765 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1785 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1786 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1789 auto processor = Processor::MakeProcessor(
1793 auto addNode = [&](
NodeId nodeid) {
1806 for (
NodeId id = 100;
id < 108;
id++) {
1811 minAvaproofsMessages <= 0);
1813 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1816 processor->avaproofsSent(i);
1820 processor->avaproofsSent(i);
1826 addNode(minAvaproofsMessages);
1827 processor->avaproofsSent(minAvaproofsMessages);
1831 AvalancheTest::clearavaproofsNodeCounter(*processor);
1835 checkMinAvaproofsMessages(0);
1836 checkMinAvaproofsMessages(1);
1837 checkMinAvaproofsMessages(10);
1838 checkMinAvaproofsMessages(100);
1843 setArg(
"-avastalevotethreshold",
1845 setArg(
"-avastalevotefactor",
"2");
1847 setArg(
"-avalanchestakingpreconsensus",
"0");
1849 const std::vector<std::tuple<int, int>> testCases = {
1856 m_node.avalanche = Processor::MakeProcessor(
1865 const uint32_t invType = provider.invType;
1867 const auto item = provider.buildVoteItem();
1868 const auto itemid = provider.getVoteItemId(item);
1871 auto avanodes = ConnectNodes();
1872 int nextNodeIndex = 0;
1874 std::vector<avalanche::VoteItemUpdate> updates;
1875 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
1878 auto invs = getInvsForNextPoll();
1885 auto registerNewVote = [&](
const Response &resp) {
1887 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1888 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1892 for (
int i = 0; i < numYesVotes; i++) {
1894 registerNewVote(next(resp));
1897 i >= 6 ? i - 5 : 0);
1902 for (
int i = 0; i < numNeutralVotes; i++) {
1904 registerNewVote(next(resp));
1909 invs = getInvsForNextPoll();
1916 registerNewVote(next(resp));
1918 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
1919 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
1922 invs = getInvsForNextPoll();
1928 BlockProvider provider(
this);
1932 std::vector<CBlockIndex *> blockIndexes;
1936 blockIndexes.push_back(pindex);
1939 auto invs = getInvsForNextPoll();
1951 std::vector<Vote> votes;
1954 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
1955 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
1958 auto avanodes = ConnectNodes();
1959 int nextNodeIndex = 0;
1961 std::vector<avalanche::VoteItemUpdate> updates;
1962 auto registerNewVote = [&]() {
1963 Response resp = {getRound(), 0, votes};
1965 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1966 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1972 bool eleventhBlockFinalized =
false;
1973 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
1976 for (
auto &update : updates) {
1977 if (update.getStatus() == VoteStatus::Finalized &&
1978 provider.fromAnyVoteItem(update.getVoteItem())
1979 ->GetBlockHash() == eleventhBlockHash) {
1980 eleventhBlockFinalized =
true;
1991 invs = getInvsForNextPoll();
1993 for (
size_t i = 0; i < 10; i++) {
2007 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2009 activeChainstate.InvalidateBlock(state, tip);
2012 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2015 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2023 activeChainstate.ResetBlockFailureFlags(tip);
2025 activeChainstate.ActivateBestChain(state);
2029 invs = getInvsForNextPoll();
2036 for (
auto &inv : invs) {
2037 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2040 bool tipFinalized =
false;
2041 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2044 for (
auto &update : updates) {
2045 if (update.getStatus() == VoteStatus::Finalized &&
2046 provider.fromAnyVoteItem(update.getVoteItem())
2047 ->GetBlockHash() == tiphash) {
2048 tipFinalized =
true;
2057 invs = getInvsForNextPoll();
2065 BlockHash alttiphash = alttip->GetBlockHash();
2066 votes = {{1, alttiphash}};
2068 bool alttipInvalidated =
false;
2069 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2072 for (
auto &update : updates) {
2073 if (update.getStatus() == VoteStatus::Invalid &&
2074 provider.fromAnyVoteItem(update.getVoteItem())
2075 ->GetBlockHash() == alttiphash) {
2076 alttipInvalidated =
true;
2081 invs = getInvsForNextPoll();
2092 const int numberElementsEachType = 100;
2095 std::vector<ProofRef> proofs;
2096 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2100 proofs.emplace_back(std::move(proof));
2102 Shuffle(proofs.begin(), proofs.end(), rng);
2104 std::vector<CBlockIndex> indexes;
2105 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2108 indexes.emplace_back(std::move(index));
2110 Shuffle(indexes.begin(), indexes.end(), rng);
2112 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2113 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2119 for (
size_t i = 0; i < numberElementsEachType; i++) {
2121 const size_t firstType = rng.
randrange(numTypes);
2123 for (
size_t j = 0; j < numTypes; j++) {
2124 switch ((firstType + j) % numTypes) {
2127 writeView->insert(std::make_pair(
2128 std::get<0>(allItems)[i],
VoteRecord(
true)));
2132 writeView->insert(std::make_pair(
2133 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2144 auto readView = voteMap.getReadView();
2145 auto it = readView.begin();
2148 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2149 for (
size_t i = 0; i < numberElementsEachType; i++) {
2150 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2152 uint32_t currentScore =
2153 std::get<const ProofRef>(it->first)->getScore();
2154 BOOST_CHECK_LT(currentScore, lastScore);
2155 lastScore = currentScore;
2163 for (
size_t i = 0; i < numberElementsEachType; i++) {
2164 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2167 std::get<const CBlockIndex *>(it->first)->nChainWork;
2169 lastWork = currentWork;
2182 const auto block = std::make_shared<const CBlock>(
2183 this->CreateBlock({}, CScript(), chainstate));
2210 auto invs = AvalancheTest::getInvsForNextPoll(*
m_node.avalanche);
2223 auto now = GetTime<std::chrono::seconds>();
2229 std::vector<CScript> winners;
2232 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2237 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2242 prevBlock.
nTime = now.count();
2247 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2250 size_t numProofs = 10;
2251 std::vector<ProofRef> proofs;
2252 proofs.reserve(numProofs);
2253 for (
size_t i = 0; i < numProofs; i++) {
2257 auto proof = GetProof(payoutScript);
2263 return pm.setFinalized(peer.peerid);
2267 proofs.emplace_back(std::move(proof));
2275 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2278 auto winnerExists = [&](
const CScript &expectedWinner) {
2279 const std::string winnerString =
FormatScript(expectedWinner);
2281 for (
const ProofRef &proof : proofs) {
2292 prevBlock.
nTime = now.count();
2297 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2303 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2309 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2313 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2318 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2322 m_node.avalanche->cleanupStakingRewards(101);
2326 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2330 m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2336 m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2340 m_node.avalanche->cleanupStakingRewards(200);
2344 !
m_node.avalanche->getStakingRewardWinners(prevBlockHash, winners));
2346 !
m_node.avalanche->getStakingRewardWinners(prevBlockHashHigh, winners));
2358 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2364 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2372 auto localProof = buildProof(outpoint, 1, 100);
2375 setArg(
"-avaproof", localProof->ToHex());
2376 setArg(
"-avalancheconflictingproofcooldown",
"0");
2377 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2378 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2382 m_node.avalanche = Processor::MakeProcessor(
2387 localProof->getId());
2389 auto checkLocalProofState = [&](
const bool boundToPeer,
2394 return pm.isBoundToPeer(localProof->getId());
2397 BOOST_CHECK_MESSAGE(
2398 m_node.avalanche->getLocalProofRegistrationState().GetResult() ==
2400 m_node.avalanche->getLocalProofRegistrationState().ToString());
2407 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2411 AvalancheTest::setLocalProofShareable(*
m_node.avalanche,
true);
2413 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2414 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2418 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2419 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2423 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2427 auto conflictingProof = buildProof(outpoint, 2, 100);
2433 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2434 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2438 setArg(
"-avalancheconflictingproofcooldown",
"0");
2439 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2459 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2466 auto proof = buildProof(outpoint, 1);
2485 AvalancheTest::addProofToRecentfinalized(*
m_node.avalanche, proof->
getId());
2492 return peer.hasFinalized;
2499 auto betterProof = buildProof(outpoint, 2);
2522 m_node.avalanche = Processor::MakeProcessor(
2528 auto now = GetTime<std::chrono::seconds>();
2531 AvalancheTest::setStakingPreconsensus(*
m_node.avalanche,
true);
2539 const ProofId proofid1 = proof1->getId();
2544 const ProofId proofid2 = proof2->getId();
2555 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2557 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2563 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2568 for (
NodeId n = 0; n < 8; n++) {
2573 return pm.setFinalized(peer.peerid);
2582 CBlock block = CreateAndProcessBlock({}, CScript());
2585 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2586 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2592 std::vector<CScript> winners;
2596 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2601 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2605 m_node.avalanche->getStakeContenderStatus(contender1_block1), -2);
2607 m_node.avalanche->getStakeContenderStatus(contender2_block1), -2);
2613 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2619 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2627 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2630 m_node.avalanche->getStakeContenderStatus(contender1_block1), -1);
2632 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2635 m_node.avalanche->getStakeContenderStatus(contender2_block1), -1);
2637 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2640 m_node.avalanche->setStakingRewardWinners(
2641 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2646 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2649 m_node.avalanche->getStakeContenderStatus(contender2_block2), 0);
2652 m_node.avalanche->withPeerManager(
2658 const ProofId proofid3 = proof3->getId();
2661 for (
NodeId n = 0; n < 8; n++) {
2667 block = CreateAndProcessBlock({}, CScript());
2670 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2671 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2675 m_node.avalanche->getStakeContenderStatus(unknownContender), -1);
2679 m_node.avalanche->getStakeContenderStatus(contender1_block2), -1);
2681 m_node.avalanche->getStakeContenderStatus(contender2_block2), -1);
2688 m_node.avalanche->getStakeContenderStatus(contender1_block3), -1);
2692 m_node.avalanche->getStakeContenderStatus(contender2_block3), -1);
2695 m_node.avalanche->withPeerManager(
2699 size_t numProofs = 8;
2700 std::vector<ProofRef> proofs;
2701 proofs.reserve(numProofs);
2702 for (
size_t i = 0; i < numProofs; i++) {
2711 return pm.setFinalized(peer.peerid);
2714 proofs.emplace_back(std::move(proof));
2719 const ProofId proofid = proofs[0]->getId();
2720 for (
NodeId n = 0; n < 8; n++) {
2730 std::vector<CScript> winners;
2731 for (
int attempt = 0; attempt < 10; attempt++) {
2733 block = CreateAndProcessBlock({}, CScript());
2736 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2737 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2743 chaintip->GetBlockHash(), winners));
2744 if (winners.size() == 8) {
2752 size_t numAccepted = 0;
2753 for (
const auto &proof : proofs) {
2757 if (
m_node.avalanche->getStakeContenderStatus(contender) == 0) {
2759 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2767 block = CreateAndProcessBlock({}, CScript());
2770 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2775 m_node.avalanche->withPeerManager(
2777 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2786 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2787 bestproof->getPayoutScript()) == winners.end());
2794 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2805 block = CreateAndProcessBlock({}, CScript());
2808 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2809 AvalancheTest::updatedBlockTip(*
m_node.avalanche);
2810 AvalancheTest::setFinalizationTip(*
m_node.avalanche, chaintip);
2817 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2831 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2832 bestproof->getPayoutScript()) == winners.end());
2840 m_node.avalanche->getStakeContenderStatus(bestcontender), 0);
2851 auto now = GetTime<std::chrono::seconds>();
2855 auto localWinnerProof =
2857 ProofId localWinnerProofId = localWinnerProof->getId();
2859 localWinnerProof->getId());
2868 for (
NodeId n = 0; n < 8; n++) {
2869 pm.
addNode(n, localWinnerProofId);
2872 return pm.setFinalized(peer.peerid);
2879 chaintip->
nTime = now.count();
2885 std::vector<ProofRef> acceptedContenderProofs;
2886 acceptedContenderProofs.push_back(localWinnerProof);
2893 for (
size_t numContenders = 2;
2897 m_node.avalanche->withPeerManager(
2903 if (rank <= bestRank) {
2905 acceptedContenderProofs.push_back(proof);
2906 const size_t numAccepted =
2908 acceptedContenderProofs.size());
2909 std::sort(acceptedContenderProofs.begin(),
2910 acceptedContenderProofs.begin() + numAccepted,
2912 const ProofId leftProofId = left->getId();
2913 const ProofId rightProofId = right->getId();
2914 const StakeContenderId leftContenderId(chaintipHash,
2916 const StakeContenderId rightContenderId(chaintipHash,
2918 return RewardRankComparator()(
2920 leftContenderId.ComputeProofRewardRank(
2921 MIN_VALID_PROOF_SCORE),
2922 leftProofId, rightContenderId,
2923 rightContenderId.ComputeProofRewardRank(
2924 MIN_VALID_PROOF_SCORE),
2929 std::vector<StakeContenderId> pollableContenders;
2930 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
2931 *
m_node.avalanche, chaintip, pollableContenders));
2933 pollableContenders.size(),
2938 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
2942 chaintipHash, acceptedContenderProofs[i]->getId());
2944 std::find(pollableContenders.begin(), pollableContenders.end(),
2945 acceptedContenderId) != pollableContenders.end());
2947 m_node.avalanche->getStakeContenderStatus(acceptedContenderId),
2952 std::set<StakeContenderId> unacceptedContenderIds(
2953 pollableContenders.begin(), pollableContenders.end());
2954 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
2956 chaintipHash, acceptedContenderProof->getId());
2957 unacceptedContenderIds.erase(acceptedContenderId);
2960 for (
auto cid : unacceptedContenderIds) {
2967 m_node.avalanche->getStakeContenderStatus(localWinnerContenderId),
2972BOOST_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...
uint64_t randrange(uint64_t range) noexcept
Generate a random integer in the range [0..range).
256-bit unsigned big integer.
bool removeNode(NodeId nodeid)
uint32_t getConnectedPeersScore() const
bool isDangling(const ProofId &proofid) const
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
bool addNode(NodeId nodeid, const ProofId &proofid)
Node API.
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.
std::vector< CInv > getInvsForNextPoll(bool forPoll=true) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
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::atomic< int64_t > avaproofsNodeCounter
std::atomic_bool m_stakingPreConsensus
Mutex cs_peerManager
Keep track of the peers and associated infos.
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
unsigned int size() const
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
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 AVALANCHE_CONTENDER_MAX_POLLABLE
Maximum number of stake contenders to poll for, leaving room for polling blocks and proofs in the sam...
static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
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.
uint256 GetRandHash() noexcept
void Shuffle(I first, I last, R &&rng)
More efficient than using std::shuffle on a FastRandomContext.
reverse_range< T > reverse_iterate(T &x)
static uint16_t GetDefaultPort()
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.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
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 const int PROTOCOL_VERSION
network protocol versioning
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.