25#include <test/util/setup_common.h>
27#include <boost/mpl/list.hpp>
28#include <boost/test/unit_test.hpp>
39 struct AvalancheTest {
42 static std::vector<CInv> getInvsForNextPoll(
Processor &p) {
48 return p.peerManager->selectNode());
53 static uint32_t getMinQuorumScore(
const Processor &p) {
57 static double getMinQuorumConnectedScoreRatio(
const Processor &p) {
61 static void clearavaproofsNodeCounter(
Processor &p) {
68 std::make_pair(item, voteRecord));
75 static void setFinalizationTip(
Processor &p,
78 p.finalizationTip = pindex;
81 static void setLocalProofShareable(
Processor &p,
bool shareable) {
87 static void addProofToRecentfinalized(
Processor &p,
90 return p.finalizedItems.insert(proofid));
93 static bool setContenderStatusForLocalWinners(
95 std::vector<StakeContenderId> &pollableContenders) {
110struct CConnmanTest :
public CConnman {
114 m_nodes.push_back(&
node);
131struct AvalancheTestingSetup :
public TestChain100Setup {
132 const ::Config &config;
133 CConnmanTest *m_connman;
135 std::unique_ptr<Processor> m_processor;
140 std::unordered_set<std::string> m_overridden_args;
142 AvalancheTestingSetup()
143 : TestChain100Setup(), config(
GetConfig()),
144 masterpriv(
CKey::MakeCompressedKey()) {
146 auto connman = std::make_unique<CConnmanTest>(config, 0x1337, 0x1337,
148 m_connman = connman.get();
149 m_node.connman = std::move(connman);
152 setArg(
"-avaminquorumstake",
"0");
153 setArg(
"-avaminquorumconnectedstakeratio",
"0");
154 setArg(
"-avaminavaproofsnodecount",
"0");
155 setArg(
"-avaproofstakeutxoconfirmations",
"1");
157 m_processor = Processor::MakeProcessor(
165 *
m_node.mempool, m_processor.get(), {});
169 ~AvalancheTestingSetup() {
170 m_connman->ClearNodes();
174 for (
const std::string &key : m_overridden_args) {
177 m_overridden_args.clear();
185 new CNode(
id++,
nullptr, addr,
192 node->m_has_all_wanted_services =
196 node->fSuccessfullyConnected =
true;
198 m_connman->AddNode(*
node);
207 const uint32_t height = 100;
216 BOOST_CHECK(pb.addUTXO(outpoint, amount, height,
false, key));
222 return pm.
addNode(nodeid, proofid);
226 bool addNode(
NodeId nodeid) {
227 auto proof = GetProof();
230 pm.
addNode(nodeid, proof->getId());
234 std::array<CNode *, 8> ConnectNodes() {
235 auto proof = GetProof();
238 return pm.registerProof(proof);
240 const ProofId &proofid = proof->getId();
242 std::array<CNode *, 8> nodes;
243 for (
CNode *&n : nodes) {
251 void runEventLoop() { AvalancheTest::runEventLoop(*m_processor); }
253 NodeId getSuitableNodeToQuery() {
254 return AvalancheTest::getSuitableNodeToQuery(*m_processor);
257 std::vector<CInv> getInvsForNextPoll() {
258 return AvalancheTest::getInvsForNextPoll(*m_processor);
261 uint64_t getRound()
const {
return AvalancheTest::getRound(*m_processor); }
264 std::vector<avalanche::VoteItemUpdate> &updates,
265 std::string &
error) {
267 return m_processor->registerVotes(nodeid,
response, updates, banscore,
272 std::vector<avalanche::VoteItemUpdate> &updates) {
275 return m_processor->registerVotes(nodeid,
response, updates, banscore,
279 void setArg(std::string key,
const std::string &value) {
282 m_overridden_args.emplace(std::move(key));
286 return m_processor->addToReconcile(item);
290struct BlockProvider {
291 AvalancheTestingSetup *fixture;
294 BlockProvider(AvalancheTestingSetup *_fixture)
295 : fixture(_fixture), invType(
MSG_BLOCK) {}
298 CBlock block = fixture->CreateAndProcessBlock({}, CScript());
302 return Assert(fixture->m_node.chainman)
303 ->m_blockman.LookupBlockIndex(blockHash);
310 std::vector<Vote> buildVotesForItems(uint32_t
error,
311 std::vector<CBlockIndex *> &&items) {
312 size_t numItems = items.
size();
314 std::vector<Vote> votes;
315 votes.reserve(numItems);
320 votes.emplace_back(
error, item->GetBlockHash());
328 pindex->nStatus = pindex->nStatus.withFailed();
332 return std::get<const CBlockIndex *>(item);
336struct ProofProvider {
337 AvalancheTestingSetup *fixture;
340 ProofProvider(AvalancheTestingSetup *_fixture)
344 const ProofRef proof = fixture->GetProof();
352 return proof->
getId();
355 std::vector<Vote> buildVotesForItems(uint32_t
error,
356 std::vector<ProofRef> &&items) {
357 size_t numItems = items.
size();
359 std::vector<Vote> votes;
360 votes.reserve(numItems);
364 for (
auto &item : items) {
365 votes.emplace_back(
error, item->getId());
371 void invalidateItem(
const ProofRef &proof) {
379 return std::get<const ProofRef>(item);
383struct StakeContenderProvider {
384 AvalancheTestingSetup *fixture;
386 std::vector<avalanche::VoteItemUpdate> updates;
389 StakeContenderProvider(AvalancheTestingSetup *_fixture)
397 std::vector<CScript> winners;
398 if (!fixture->m_processor->getStakingRewardWinners(
402 const ProofRef proofWinner = fixture->GetProof();
404 fixture->m_processor->setStakingRewardWinners(chaintip, payouts);
408 const ProofRef proof = fixture->GetProof();
414 fixture->m_processor->addStakeContender(proof);
420 fixture->m_processor->acceptStakeContender(contenderId);
424 fixture->m_processor->getStakeContenderStatus(contenderId) == 0);
433 buildVotesForItems(uint32_t
error, std::vector<StakeContenderId> &&items) {
434 size_t numItems = items.
size();
436 std::vector<Vote> votes;
437 votes.reserve(numItems);
440 std::sort(items.begin(), items.end(),
444 for (
auto &item : items) {
445 votes.emplace_back(
error, item);
452 fixture->m_processor->invalidateStakeContender(contenderId);
460 AvalancheTest::removeVoteRecord(*(fixture->m_processor),
465 return std::get<const StakeContenderId>(item);
470 AvalancheTestingSetup *fixture;
472 std::vector<avalanche::VoteItemUpdate> updates;
475 TxProvider(AvalancheTestingSetup *_fixture)
476 : fixture(_fixture), invType(
MSG_TX) {}
486 TestMemPoolEntryHelper mempoolEntryHelper;
487 auto entry = mempoolEntryHelper.FromTx(tx);
503 std::vector<Vote> buildVotesForItems(uint32_t
error,
504 std::vector<CTransactionRef> &&items) {
505 size_t numItems = items.
size();
507 std::vector<Vote> votes;
508 votes.reserve(numItems);
511 std::sort(items.begin(), items.end(),
513 return lhs->GetId() < rhs->GetId();
515 for (
auto &item : items) {
516 votes.emplace_back(
error, item->GetId());
532 return std::get<const CTransactionRef>(item);
538BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheTestingSetup)
542 StakeContenderProvider, TxProvider>;
544 boost::mpl::list<BlockProvider, ProofProvider, TxProvider>;
553 std::set<VoteStatus> status{
554 VoteStatus::Invalid, VoteStatus::Rejected, VoteStatus::Accepted,
555 VoteStatus::Finalized, VoteStatus::Stale,
558 auto item = provider.buildVoteItem();
560 for (
auto s : status) {
583 auto item = provider.buildVoteItem();
584 auto itemid = provider.getVoteItemId(item);
592 auto avanodes = ConnectNodes();
594 int nextNodeIndex = 0;
595 std::vector<avalanche::VoteItemUpdate> updates;
596 auto registerNewVote = [&](
const Response &resp) {
598 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
603 auto finalize = [&](
const auto finalizeItemId) {
604 Response resp = {getRound(), 0, {
Vote(0, finalizeItemId)}};
606 registerNewVote(next(resp));
607 if (updates.size() > 0) {
612 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
619 auto finalizeNewItem = [&]() {
620 auto anotherItem = provider.buildVoteItem();
622 auto anotherItemId = provider.getVoteItemId(anotherItem);
625 AvalancheTest::addVoteRecord(*m_processor, anotherVoteItem, voteRecord);
626 finalize(anotherItemId);
646 AvalancheTest::setFinalizationTip(*m_processor, chaintip);
658 auto item =
decltype(provider.buildVoteItem())();
665 item = provider.buildVoteItem();
675 auto itemZero =
decltype(provider.buildVoteItem())();
687 auto item = provider.buildVoteItem();
696 const uint32_t invType = provider.invType;
698 auto item = provider.buildVoteItem();
699 auto itemid = provider.getVoteItemId(item);
702 auto avanodes = ConnectNodes();
709 auto invs = getInvsForNextPoll();
716 int nextNodeIndex = 0;
717 std::vector<avalanche::VoteItemUpdate> updates;
718 auto registerNewVote = [&](
const Response &resp) {
720 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
726 for (
int i = 0; i < 6; i++) {
727 registerNewVote(next(resp));
734 resp = {getRound(), 0, {
Vote(-1, itemid)}};
735 registerNewVote(next(resp));
740 resp = {getRound(), 0, {
Vote(0, itemid)}};
741 for (
int i = 1; i < 7; i++) {
742 registerNewVote(next(resp));
749 resp = {getRound(), 0, {
Vote(-1, itemid)}};
750 registerNewVote(next(resp));
754 registerNewVote(next(resp));
759 resp = {getRound(), 0, {
Vote(0, itemid)}};
760 for (
int i = 2; i < 8; i++) {
761 registerNewVote(next(resp));
769 registerNewVote(next(resp));
776 invs = getInvsForNextPoll();
782 registerNewVote(next(resp));
784 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
785 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
788 invs = getInvsForNextPoll();
792 item = provider.buildVoteItem();
793 itemid = provider.getVoteItemId(item);
797 invs = getInvsForNextPoll();
802 resp = {getRound(), 0, {
Vote(1, itemid)}};
803 for (
int i = 0; i < 6; i++) {
804 registerNewVote(next(resp));
810 registerNewVote(next(resp));
813 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
814 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
818 registerNewVote(next(resp));
824 invs = getInvsForNextPoll();
830 registerNewVote(next(resp));
833 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
834 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
837 invs = getInvsForNextPoll();
843 const uint32_t invType = provider.invType;
845 auto itemA = provider.buildVoteItem();
846 auto itemidA = provider.getVoteItemId(itemA);
848 auto itemB = provider.buildVoteItem();
849 auto itemidB = provider.getVoteItemId(itemB);
852 auto avanodes = ConnectNodes();
860 auto invs = getInvsForNextPoll();
865 uint64_t round = getRound();
867 std::vector<avalanche::VoteItemUpdate> updates;
869 {round, 0, {
Vote(0, itemidA)}}, updates));
873 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
876 invs = getInvsForNextPoll();
880 for (
size_t i = 0; i < invs.size(); i++) {
886 for (
int i = 0; i < 4; i++) {
887 NodeId nodeid = getSuitableNodeToQuery();
889 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
895 NodeId nodeid = getSuitableNodeToQuery();
897 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
903 NodeId firstNodeid = getSuitableNodeToQuery();
905 NodeId secondNodeid = getSuitableNodeToQuery();
911 BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates));
913 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemA);
914 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
917 invs = getInvsForNextPoll();
923 BOOST_CHECK(registerVotes(secondNodeid, resp, updates));
925 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemB);
926 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
929 invs = getInvsForNextPoll();
935 const uint32_t invType = provider.invType;
937 auto item = provider.buildVoteItem();
938 auto itemid = provider.getVoteItemId(item);
945 std::set<NodeId> avanodeIds;
946 auto avanodes = ConnectNodes();
947 for (
auto avanode : avanodes) {
949 avanodeIds.insert(avanode->GetId());
952 auto getSelectedAvanodeId = [&]() {
953 NodeId avanodeid = getSuitableNodeToQuery();
954 BOOST_CHECK(avanodeIds.find(avanodeid) != avanodeIds.end());
959 NodeId avanodeid = getSelectedAvanodeId();
963 auto invs = getInvsForNextPoll();
968 std::set<NodeId> unselectedNodeids = avanodeIds;
969 unselectedNodeids.erase(avanodeid);
970 const size_t remainingNodeIds = unselectedNodeids.size();
972 uint64_t round = getRound();
973 for (
size_t i = 0; i < remainingNodeIds; i++) {
978 NodeId nodeid = getSuitableNodeToQuery();
979 BOOST_CHECK(unselectedNodeids.find(nodeid) != avanodeIds.end());
980 unselectedNodeids.erase(nodeid);
990 std::vector<avalanche::VoteItemUpdate> updates;
991 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
998 auto checkRegisterVotesError = [&](
NodeId nodeid,
1000 const std::string &expectedError) {
1008 checkRegisterVotesError(avanodeid, next(resp),
"unexpected-ava-response");
1017 resp = {round, 0, {
Vote(0, itemid),
Vote(0, itemid)}};
1019 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
1023 resp = {getRound(), 0, {}};
1025 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
1029 resp = {getRound(), 0, {
Vote()}};
1031 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1038 invs = getInvsForNextPoll();
1041 item = provider.buildVoteItem();
1042 itemid = provider.getVoteItemId(item);
1045 invs = getInvsForNextPoll();
1049 uint64_t queryRound = getRound();
1052 resp = {queryRound + 1, 0, {
Vote()}};
1053 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1055 resp = {queryRound - 1, 0, {
Vote()}};
1056 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1060 resp = {queryRound, 0, {
Vote(0, itemid)}};
1061 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1064 resp = {queryRound, 0, {
Vote(0, itemid)}};
1065 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1070 const auto item2 = provider.buildVoteItem();
1073 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1074 resp = {getRound(), 0, {votes[1], votes[0]}};
1076 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1080 resp = {getRound(), 0, votes};
1082 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1089 const uint32_t invType = provider.invType;
1091 auto itemA = provider.buildVoteItem();
1092 auto itemB = provider.buildVoteItem();
1094 auto avanodes = ConnectNodes();
1095 int nextNodeIndex = 0;
1098 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1104 auto invs = getInvsForNextPoll();
1106 for (
size_t i = 0; i < invs.size(); i++) {
1112 provider.invalidateItem(itemB);
1114 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1115 std::vector<avalanche::VoteItemUpdate> updates;
1118 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1119 goodResp, updates));
1123 invs = getInvsForNextPoll();
1126 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1129 Response badResp{getRound(), 0, votes};
1133 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1134 badResp, updates,
error));
1138 votes = provider.buildVotesForItems(1, {itemA});
1139 auto registerNewVote = [&]() {
1140 Response resp = {getRound(), 0, votes};
1142 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1143 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1145 for (
size_t i = 0; i < 4000; i++) {
1147 if (updates.size() > 0 &&
1148 updates[0].getStatus() == VoteStatus::Invalid) {
1154 invs = getInvsForNextPoll();
1158 badResp =
Response(getRound(), 0, votes);
1161 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1162 badResp, updates,
error));
1166BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1171 auto queryTimeDuration = std::chrono::milliseconds(10);
1172 setArg(
"-avatimeout",
ToString(queryTimeDuration.count()));
1175 m_processor = Processor::MakeProcessor(
1179 const auto item = provider.buildVoteItem();
1180 const auto itemid = provider.getVoteItemId(item);
1190 for (
int i = 0; i < 10; i++) {
1192 avanodeid = getSuitableNodeToQuery();
1194 auto start = Now<SteadyMilliseconds>();
1198 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1201 std::vector<avalanche::VoteItemUpdate> updates;
1202 bool ret = registerVotes(avanodeid, next(resp), updates);
1203 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1214 avanodeid = getSuitableNodeToQuery();
1218 std::this_thread::sleep_for(queryTimeDuration);
1220 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1226 const uint32_t invType = provider.invType;
1229 auto proof = GetProof();
1233 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1234 for (
auto &n : nodes) {
1240 const auto item = provider.buildVoteItem();
1241 const auto itemid = provider.getVoteItemId(item);
1245 std::map<NodeId, uint64_t> node_round_map;
1247 NodeId nodeid = getSuitableNodeToQuery();
1248 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1249 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1250 auto invs = getInvsForNextPoll();
1258 auto suitablenodeid = getSuitableNodeToQuery();
1260 auto invs = getInvsForNextPoll();
1266 auto it = node_round_map.begin();
1268 std::vector<avalanche::VoteItemUpdate> updates;
1269 BOOST_CHECK(registerVotes(it->first, resp, updates));
1270 node_round_map.erase(it);
1272 invs = getInvsForNextPoll();
1279 std::vector<VoteItemUpdate> updates;
1281 CBlock block = CreateAndProcessBlock({}, CScript());
1287 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1291 auto avanodes = ConnectNodes();
1300 uint64_t round = getRound();
1304 for (
size_t i = 0; i < avanodes.size(); i++) {
1306 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1310 const NodeId firstNodeId = getSuitableNodeToQuery();
1311 std::map<NodeId, uint64_t> node_round_map;
1313 for (
size_t i = 0; i < avanodes.size(); i++) {
1314 NodeId nodeid = getSuitableNodeToQuery();
1315 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1316 node_round_map[nodeid] = getRound();
1322 auto confidence = m_processor->getConfidence(pindex);
1323 BOOST_REQUIRE(confidence > 0);
1325 for (
auto &[nodeid, r] : node_round_map) {
1326 if (nodeid == firstNodeId) {
1333 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1338 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1345 CBlock block = CreateAndProcessBlock({}, CScript());
1351 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1358 std::chrono::steady_clock::time_point start,
stop;
1368 auto avanodes = ConnectNodes();
1371 NodeId nodeid = getSuitableNodeToQuery();
1372 BOOST_CHECK_NE(nodeid,
NO_NODE);
1375 uint64_t queryRound = getRound();
1379 for (
int i = 0; i < 60 * 1000; i++) {
1383 if (getRound() == queryRound + avanodes.size()) {
1392 uint64_t responseRound = getRound();
1393 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1395 std::vector<VoteItemUpdate> updates;
1397 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1400 for (
int i = 0; i < 10000; i++) {
1403 if (getRound() != responseRound) {
1404 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1423 schedulerThread.join();
1428 std::chrono::steady_clock::time_point start,
stop;
1430 std::thread schedulerThread;
1440 m_processor.reset();
1447 schedulerThread.join();
1454 auto addProofToReconcile = [&](uint32_t proofScore) {
1464 auto proof = addProofToReconcile(++score);
1466 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1475 for (
size_t i = 0; i < 10; i++) {
1476 auto proof = addProofToReconcile(++score);
1478 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1483 lastProofId = proof->
getId();
1486 for (
size_t i = 0; i < 10; i++) {
1487 auto proof = addProofToReconcile(--score);
1489 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1497 auto proof = addProofToReconcile(--score);
1498 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1499 for (
auto &inv : invs) {
1500 BOOST_CHECK_NE(inv.hash, proof->
getId());
1506 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1507 setArg(
"-avalancheconflictingproofcooldown",
"0");
1521 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1522 coins.
AddCoin(conflictingOutpoint,
1525 coins.
AddCoin(immatureOutpoint,
1530 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1531 uint32_t height = 10) {
1538 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1539 auto validProof = buildProof(conflictingOutpoint, 2);
1540 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1542 BOOST_CHECK(!m_processor->isAccepted(conflictingProof));
1543 BOOST_CHECK(!m_processor->isAccepted(validProof));
1544 BOOST_CHECK(!m_processor->isAccepted(immatureProof));
1550 BOOST_CHECK(!m_processor->addToReconcile(conflictingProof));
1551 BOOST_CHECK(!m_processor->addToReconcile(validProof));
1552 BOOST_CHECK(!m_processor->addToReconcile(immatureProof));
1564 BOOST_CHECK(m_processor->addToReconcile(conflictingProof));
1565 BOOST_CHECK(!m_processor->isAccepted(conflictingProof));
1566 BOOST_CHECK(!m_processor->isAccepted(validProof));
1567 BOOST_CHECK(!m_processor->isAccepted(immatureProof));
1572 BOOST_CHECK(m_processor->addToReconcile(validProof));
1573 BOOST_CHECK(!m_processor->isAccepted(conflictingProof));
1575 BOOST_CHECK(!m_processor->isAccepted(immatureProof));
1580 BOOST_CHECK(!m_processor->addToReconcile(immatureProof));
1581 BOOST_CHECK(!m_processor->isAccepted(conflictingProof));
1583 BOOST_CHECK(!m_processor->isAccepted(immatureProof));
1591 int minStake = 400'000'000;
1592 setArg(
"-avaminquorumstake",
ToString(minStake));
1593 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1597 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1605 setArg(
"-avaproof", localProof->ToHex());
1609 m_processor = Processor::MakeProcessor(
1614 BOOST_CHECK(m_processor->getLocalProof() !=
nullptr);
1616 localProof->getId());
1619 AvalancheTest::getMinQuorumConnectedScoreRatio(*m_processor), 0.5);
1640 for (
NodeId id = 0;
id < 8;
id++) {
1642 pm.
addNode(
id, m_processor->getLocalProof()->getId());
1658 const int64_t tipTime =
1662 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1663 const int height = 100;
1664 const bool isCoinbase =
false;
1671 height, isCoinbase),
1676 auto proof2 = pb.
build();
1687 pm.
addNode(8, proof2->getId());
1706 m_processor->withPeerManager(
1712 pm.
addNode(7, m_processor->getLocalProof()->getId());
1717 auto spendProofUtxo = [&](
ProofRef proof) {
1730 for (int64_t i = 0; i < 6; i++) {
1732 CreateAndProcessBlock({}, CScript());
1736 ->GetMedianTimePast(),
1737 proof2->getExpirationTime());
1748 spendProofUtxo(proof1);
1755 spendProofUtxo(m_processor->getLocalProof());
1767 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1770 {
"",
"",
"",
false},
1771 {
"-1",
"-1",
"-1",
false},
1774 {
"-1",
"0",
"0",
false},
1775 {
"-0.01",
"0",
"0",
false},
1776 {
"21000000000000.01",
"0",
"0",
false},
1779 {
"0",
"-1",
"0",
false},
1780 {
"0",
"1.1",
"0",
false},
1783 {
"0",
"0",
"-1",
false},
1786 {
"0",
"0",
"0",
true},
1787 {
"0.00",
"0",
"0",
true},
1788 {
"0.01",
"0",
"0",
true},
1789 {
"1",
"0.1",
"0",
true},
1790 {
"10",
"0.5",
"0",
true},
1791 {
"10",
"1",
"0",
true},
1792 {
"21000000000000.00",
"0",
"0",
true},
1793 {
"0",
"0",
"1",
true},
1794 {
"0",
"0",
"100",
true},
1799 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1801 setArg(
"-avaminquorumstake", stake);
1802 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1803 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1806 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1826 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1827 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1830 auto processor = Processor::MakeProcessor(
1834 auto addNode = [&](
NodeId nodeid) {
1847 for (
NodeId id = 100;
id < 108;
id++) {
1852 minAvaproofsMessages <= 0);
1854 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1857 processor->avaproofsSent(i);
1861 processor->avaproofsSent(i);
1867 addNode(minAvaproofsMessages);
1868 processor->avaproofsSent(minAvaproofsMessages);
1872 AvalancheTest::clearavaproofsNodeCounter(*processor);
1876 checkMinAvaproofsMessages(0);
1877 checkMinAvaproofsMessages(1);
1878 checkMinAvaproofsMessages(10);
1879 checkMinAvaproofsMessages(100);
1884 setArg(
"-avastalevotethreshold",
1886 setArg(
"-avastalevotefactor",
"2");
1888 const std::vector<std::tuple<int, int>> testCases = {
1895 m_processor = Processor::MakeProcessor(
1904 const uint32_t invType = provider.invType;
1906 const auto item = provider.buildVoteItem();
1907 const auto itemid = provider.getVoteItemId(item);
1910 auto avanodes = ConnectNodes();
1911 int nextNodeIndex = 0;
1913 std::vector<avalanche::VoteItemUpdate> updates;
1914 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
1917 auto invs = getInvsForNextPoll();
1924 auto registerNewVote = [&](
const Response &resp) {
1926 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1927 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1931 for (
int i = 0; i < numYesVotes; i++) {
1933 registerNewVote(next(resp));
1936 i >= 6 ? i - 5 : 0);
1941 for (
int i = 0; i < numNeutralVotes; i++) {
1943 registerNewVote(next(resp));
1948 invs = getInvsForNextPoll();
1955 registerNewVote(next(resp));
1957 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
1958 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
1961 invs = getInvsForNextPoll();
1967 BlockProvider provider(
this);
1971 std::vector<CBlockIndex *> blockIndexes;
1975 blockIndexes.push_back(pindex);
1978 auto invs = getInvsForNextPoll();
1990 std::vector<Vote> votes;
1993 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
1994 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
1997 auto avanodes = ConnectNodes();
1998 int nextNodeIndex = 0;
2000 std::vector<avalanche::VoteItemUpdate> updates;
2001 auto registerNewVote = [&]() {
2002 Response resp = {getRound(), 0, votes};
2004 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
2005 BOOST_CHECK(registerVotes(nodeid, resp, updates));
2011 bool eleventhBlockFinalized =
false;
2012 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
2015 for (
auto &update : updates) {
2016 if (update.getStatus() == VoteStatus::Finalized &&
2017 provider.fromAnyVoteItem(update.getVoteItem())
2018 ->GetBlockHash() == eleventhBlockHash) {
2019 eleventhBlockFinalized =
true;
2030 invs = getInvsForNextPoll();
2032 for (
size_t i = 0; i < 10; i++) {
2046 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2048 activeChainstate.InvalidateBlock(state, tip);
2051 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2054 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2062 activeChainstate.ResetBlockFailureFlags(tip);
2064 activeChainstate.ActivateBestChain(state);
2068 invs = getInvsForNextPoll();
2075 for (
auto &inv : invs) {
2076 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2079 bool tipFinalized =
false;
2080 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2083 for (
auto &update : updates) {
2084 if (update.getStatus() == VoteStatus::Finalized &&
2085 provider.fromAnyVoteItem(update.getVoteItem())
2086 ->GetBlockHash() == tiphash) {
2087 tipFinalized =
true;
2096 invs = getInvsForNextPoll();
2104 BlockHash alttiphash = alttip->GetBlockHash();
2105 votes = {{1, alttiphash}};
2107 bool alttipInvalidated =
false;
2108 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2111 for (
auto &update : updates) {
2112 if (update.getStatus() == VoteStatus::Invalid &&
2113 provider.fromAnyVoteItem(update.getVoteItem())
2114 ->GetBlockHash() == alttiphash) {
2115 alttipInvalidated =
true;
2120 invs = getInvsForNextPoll();
2131 const int numberElementsEachType = 100;
2134 std::vector<ProofRef> proofs;
2135 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2139 proofs.emplace_back(std::move(proof));
2141 Shuffle(proofs.begin(), proofs.end(), rng);
2143 std::vector<CBlockIndex> indexes;
2144 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2147 indexes.emplace_back(std::move(index));
2149 Shuffle(indexes.begin(), indexes.end(), rng);
2151 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2152 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2158 for (
size_t i = 0; i < numberElementsEachType; i++) {
2160 const size_t firstType = rng.
randrange(numTypes);
2162 for (
size_t j = 0; j < numTypes; j++) {
2163 switch ((firstType + j) % numTypes) {
2166 writeView->insert(std::make_pair(
2167 std::get<0>(allItems)[i],
VoteRecord(
true)));
2171 writeView->insert(std::make_pair(
2172 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2183 auto readView = voteMap.getReadView();
2184 auto it = readView.begin();
2187 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2188 for (
size_t i = 0; i < numberElementsEachType; i++) {
2189 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2191 uint32_t currentScore =
2192 std::get<const ProofRef>(it->first)->getScore();
2193 BOOST_CHECK_LT(currentScore, lastScore);
2194 lastScore = currentScore;
2202 for (
size_t i = 0; i < numberElementsEachType; i++) {
2203 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2206 std::get<const CBlockIndex *>(it->first)->nChainWork;
2208 lastWork = currentWork;
2221 const auto block = std::make_shared<const CBlock>(
2222 this->CreateBlock({}, CScript(), chainstate));
2239 BOOST_CHECK(AvalancheTest::getInvsForNextPoll(*m_processor).empty());
2240 BOOST_CHECK(!m_processor->isAccepted(blockindex));
2248 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
2261 auto now = GetTime<std::chrono::seconds>();
2267 std::vector<CScript> winners;
2269 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2272 BOOST_CHECK(!m_processor->computeStakingReward(
nullptr));
2273 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2278 prevBlock.
nTime = now.count();
2281 BOOST_CHECK(!m_processor->computeStakingReward(&prevBlock));
2282 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2285 size_t numProofs = 10;
2286 std::vector<ProofRef> proofs;
2287 proofs.reserve(numProofs);
2288 for (
size_t i = 0; i < numProofs; i++) {
2292 auto proof = GetProof(payoutScript);
2298 return pm.setFinalized(peer.peerid);
2302 proofs.emplace_back(std::move(proof));
2308 BOOST_CHECK(!m_processor->computeStakingReward(&prevBlock));
2309 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2312 auto winnerExists = [&](
const CScript &expectedWinner) {
2313 const std::string winnerString =
FormatScript(expectedWinner);
2315 for (
const ProofRef &proof : proofs) {
2326 prevBlock.
nTime = now.count();
2329 BOOST_CHECK(m_processor->computeStakingReward(&prevBlock));
2330 BOOST_CHECK(m_processor->getStakingRewardWinners(prevBlockHash, winners));
2334 BOOST_CHECK(m_processor->computeStakingReward(&prevBlock));
2335 BOOST_CHECK(m_processor->getStakingRewardWinners(prevBlockHash, winners));
2341 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2343 BOOST_CHECK(m_processor->computeStakingReward(&prevBlockHigh));
2345 m_processor->getStakingRewardWinners(prevBlockHashHigh, winners));
2349 BOOST_CHECK(m_processor->getStakingRewardWinners(prevBlockHash, winners));
2353 m_processor->cleanupStakingRewards(101);
2356 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2360 m_processor->getStakingRewardWinners(prevBlockHashHigh, winners));
2364 BOOST_CHECK(m_processor->computeStakingReward(&prevBlock));
2365 BOOST_CHECK(m_processor->getStakingRewardWinners(prevBlockHash, winners));
2369 m_processor->cleanupStakingRewards(200);
2372 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2374 !m_processor->getStakingRewardWinners(prevBlockHashHigh, winners));
2386 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2392 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2400 auto localProof = buildProof(outpoint, 1, 100);
2403 setArg(
"-avaproof", localProof->ToHex());
2404 setArg(
"-avalancheconflictingproofcooldown",
"0");
2405 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2406 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2410 m_processor = Processor::MakeProcessor(
2415 localProof->getId());
2417 auto checkLocalProofState =
2418 [&](
const bool boundToPeer,
2422 return pm.isBoundToPeer(localProof->getId());
2425 BOOST_CHECK_MESSAGE(
2426 m_processor->getLocalProofRegistrationState().GetResult() ==
2428 m_processor->getLocalProofRegistrationState().ToString());
2435 AvalancheTest::updatedBlockTip(*m_processor);
2439 AvalancheTest::setLocalProofShareable(*m_processor,
true);
2441 AvalancheTest::updatedBlockTip(*m_processor);
2442 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2446 AvalancheTest::updatedBlockTip(*m_processor);
2447 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2451 AvalancheTest::updatedBlockTip(*m_processor);
2455 auto conflictingProof = buildProof(outpoint, 2, 100);
2461 AvalancheTest::updatedBlockTip(*m_processor);
2462 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2466 setArg(
"-avalancheconflictingproofcooldown",
"0");
2467 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2487 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2494 auto proof = buildProof(outpoint, 1);
2498 BOOST_CHECK(!m_processor->reconcileOrFinalize(proof));
2508 BOOST_CHECK(m_processor->reconcileOrFinalize(proof));
2510 BOOST_CHECK(!m_processor->reconcileOrFinalize(proof));
2513 AvalancheTest::addProofToRecentfinalized(*m_processor, proof->
getId());
2515 BOOST_CHECK(m_processor->reconcileOrFinalize(proof));
2520 return peer.hasFinalized;
2527 auto betterProof = buildProof(outpoint, 2);
2531 BOOST_CHECK(!m_processor->reconcileOrFinalize(betterProof));
2543 BOOST_CHECK(!m_processor->reconcileOrFinalize(proof));
2545 BOOST_CHECK(m_processor->reconcileOrFinalize(betterProof));
2549 setArg(
"-avalanchestakingpreconsensus",
"1");
2551 m_processor = Processor::MakeProcessor(
2557 auto now = GetTime<std::chrono::seconds>();
2566 const ProofId proofid1 = proof1->getId();
2571 const ProofId proofid2 = proof2->getId();
2579 m_processor->addStakeContender(proof1);
2580 m_processor->addStakeContender(proof2);
2597 for (
NodeId n = 0; n < 8; n++) {
2602 return pm.setFinalized(peer.peerid);
2607 AvalancheTest::setFinalizationTip(*m_processor, chaintip);
2614 CBlock block = CreateAndProcessBlock({}, CScript());
2617 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2618 AvalancheTest::updatedBlockTip(*m_processor);
2622 BOOST_CHECK(m_processor->computeStakingReward(chaintip));
2624 std::vector<CScript> winners;
2628 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2654 AvalancheTest::setFinalizationTip(*m_processor, chaintip);
2659 m_processor->cleanupStakingRewards(chaintip->
nHeight);
2675 m_processor->setStakingRewardWinners(
2676 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2687 m_processor->withPeerManager(
2689 block = CreateAndProcessBlock({}, CScript());
2692 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2693 AvalancheTest::updatedBlockTip(*m_processor);
2694 AvalancheTest::setFinalizationTip(*m_processor, chaintip);
2695 m_processor->cleanupStakingRewards(chaintip->
nHeight);
2718 size_t numProofs = 8;
2719 std::vector<ProofRef> proofs;
2720 proofs.reserve(numProofs);
2721 for (
size_t i = 0; i < numProofs; i++) {
2729 return pm.setFinalized(peer.peerid);
2736 proofs.emplace_back(std::move(proof));
2741 const ProofId proofid = proofs[0]->getId();
2742 for (
NodeId n = 0; n < 8; n++) {
2752 std::vector<CScript> winners;
2753 for (
int attempt = 0; attempt < 10; attempt++) {
2755 block = CreateAndProcessBlock({}, CScript());
2758 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2759 AvalancheTest::updatedBlockTip(*m_processor);
2763 BOOST_CHECK(m_processor->computeStakingReward(chaintip));
2765 chaintip->GetBlockHash(), winners));
2766 if (winners.size() == 8) {
2774 size_t numAccepted = 0;
2775 for (
const auto &proof : proofs) {
2779 if (m_processor->getStakeContenderStatus(contender) == 0) {
2781 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2789 block = CreateAndProcessBlock({}, CScript());
2792 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2794 std::numeric_limits<uint32_t>::max());
2796 AvalancheTest::updatedBlockTip(*m_processor);
2800 BOOST_CHECK(m_processor->computeStakingReward(chaintip));
2805 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2806 bestproof->getPayoutScript()) == winners.end());
2821 auto now = GetTime<std::chrono::seconds>();
2825 auto localWinnerProof =
2827 ProofId localWinnerProofId = localWinnerProof->getId();
2829 localWinnerProof->getId());
2832 m_processor->addStakeContender(localWinnerProof);
2839 for (
NodeId n = 0; n < 8; n++) {
2840 pm.
addNode(n, localWinnerProofId);
2843 return pm.setFinalized(peer.peerid);
2850 chaintip->
nTime = now.count();
2854 BOOST_CHECK(m_processor->computeStakingReward(chaintip));
2856 std::vector<ProofRef> acceptedContenderProofs;
2857 acceptedContenderProofs.push_back(localWinnerProof);
2864 for (
size_t numContenders = 2;
2870 m_processor->addStakeContender(proof);
2876 if (rank < bestRank) {
2878 acceptedContenderProofs.push_back(proof);
2879 std::sort(acceptedContenderProofs.begin(),
2880 acceptedContenderProofs.end(),
2882 const ProofId leftProofId = left->getId();
2883 const ProofId rightProofId = right->getId();
2884 const StakeContenderId leftContenderId(chaintipHash,
2886 const StakeContenderId rightContenderId(chaintipHash,
2888 return RewardRankComparator()(
2890 leftContenderId.ComputeProofRewardRank(
2891 MIN_VALID_PROOF_SCORE),
2892 leftProofId, rightContenderId,
2893 rightContenderId.ComputeProofRewardRank(
2894 MIN_VALID_PROOF_SCORE),
2899 std::vector<StakeContenderId> pollableContenders;
2900 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
2901 *m_processor, chaintip, pollableContenders));
2903 pollableContenders.size(),
2908 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
2912 chaintipHash, acceptedContenderProofs[i]->getId());
2914 std::find(pollableContenders.begin(), pollableContenders.end(),
2915 acceptedContenderId) != pollableContenders.end());
2917 m_processor->getStakeContenderStatus(acceptedContenderId), 0);
2921 std::set<StakeContenderId> unacceptedContenderIds(
2922 pollableContenders.begin(), pollableContenders.end());
2923 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
2925 chaintipHash, acceptedContenderProof->getId());
2926 unacceptedContenderIds.erase(acceptedContenderId);
2929 for (
auto cid : unacceptedContenderIds) {
2935 m_processor->getStakeContenderStatus(localWinnerContenderId), 0);
2939BOOST_AUTO_TEST_SUITE_END()
static constexpr Amount COIN
uint256 ArithToUint256(const arith_uint256 &a)
const CChainParams & Params()
Return the currently selected parameters.
#define Assert(val)
Identity function.
void ForceSetArg(const std::string &strArg, const std::string &strValue)
void ClearForcedArg(const std::string &strArg)
Remove a forced arg setting, used only in testing.
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.
CConnman(const Config &configIn, uint64_t seed0, uint64_t seed1, AddrMan &addrmanIn, bool network_active=true)
bool AddNode(const std::string &node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex)
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(std::function< void(bilingual_str)> shutdown_fnc=[](bilingual_str msg) { AbortNode(msg.original, msg);}) 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).
static std::unique_ptr< PeerManager > make(CConnman &connman, AddrMan &addrman, BanMan *banman, ChainstateManager &chainman, CTxMemPool &pool, avalanche::Processor *const avalanche, Options opts)
256-bit unsigned big integer.
bool removeNode(NodeId nodeid)
uint32_t getConnectedPeersScore() 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)
bool isInConflictingPool(const ProofId &proofid) const
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_stakeContenderCache
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
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
const Config & GetConfig()
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)
bool error(const char *fmt, const Args &...args)
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::unique_ptr< Chain > MakeChain(node::NodeContext &node, const CChainParams ¶ms)
Return implementation of Chain interface.
@ OUTBOUND_FULL_RELAY
These are the default connections that we use to connect with the network.
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.