23#include <validation.h>
26#include <test/util/setup_common.h>
28#include <boost/mpl/list.hpp>
29#include <boost/test/unit_test.hpp>
40 struct AvalancheTest {
43 static std::vector<CInv> getInvsForNextPoll(
Processor &p) {
49 return p.peerManager->selectNode());
54 static uint32_t getMinQuorumScore(
const Processor &p) {
58 static double getMinQuorumConnectedScoreRatio(
const Processor &p) {
62 static void clearavaproofsNodeCounter(
Processor &p) {
69 std::make_pair(item, voteRecord));
76 static void setFinalizationTip(
Processor &p,
79 p.finalizationTip = pindex;
82 static void setLocalProofShareable(
Processor &p,
bool shareable) {
88 static void addProofToRecentfinalized(
Processor &p,
91 return p.finalizedItems.insert(proofid));
94 static bool setContenderStatusForLocalWinners(
96 std::vector<StakeContenderId> &pollableContenders) {
111struct CConnmanTest :
public CConnman {
115 m_nodes.push_back(&
node);
132struct AvalancheTestingSetup :
public TestChain100Setup {
133 const ::Config &config;
134 CConnmanTest *m_connman;
136 std::unique_ptr<Processor> m_processor;
141 std::unordered_set<std::string> m_overridden_args;
143 AvalancheTestingSetup()
144 : TestChain100Setup(), config(
GetConfig()),
145 masterpriv(
CKey::MakeCompressedKey()) {
147 auto connman = std::make_unique<CConnmanTest>(config, 0x1337, 0x1337,
149 m_connman = connman.get();
150 m_node.connman = std::move(connman);
153 setArg(
"-avaminquorumstake",
"0");
154 setArg(
"-avaminquorumconnectedstakeratio",
"0");
155 setArg(
"-avaminavaproofsnodecount",
"0");
156 setArg(
"-avaproofstakeutxoconfirmations",
"1");
158 m_processor = Processor::MakeProcessor(
166 *
m_node.mempool, m_processor.get(), {});
170 ~AvalancheTestingSetup() {
171 m_connman->ClearNodes();
175 for (
const std::string &key : m_overridden_args) {
178 m_overridden_args.clear();
186 new CNode(
id++,
nullptr, addr,
193 node->m_has_all_wanted_services =
197 node->fSuccessfullyConnected =
true;
199 m_connman->AddNode(*
node);
208 const uint32_t height = 100;
217 BOOST_CHECK(pb.addUTXO(outpoint, amount, height,
false, key));
223 return pm.
addNode(nodeid, proofid);
227 bool addNode(
NodeId nodeid) {
228 auto proof = GetProof();
231 pm.
addNode(nodeid, proof->getId());
235 std::array<CNode *, 8> ConnectNodes() {
236 auto proof = GetProof();
239 return pm.registerProof(proof);
241 const ProofId &proofid = proof->getId();
243 std::array<CNode *, 8> nodes;
244 for (
CNode *&n : nodes) {
252 void runEventLoop() { AvalancheTest::runEventLoop(*m_processor); }
254 NodeId getSuitableNodeToQuery() {
255 return AvalancheTest::getSuitableNodeToQuery(*m_processor);
258 std::vector<CInv> getInvsForNextPoll() {
259 return AvalancheTest::getInvsForNextPoll(*m_processor);
262 uint64_t getRound()
const {
return AvalancheTest::getRound(*m_processor); }
265 std::vector<avalanche::VoteItemUpdate> &updates,
266 std::string &
error) {
268 return m_processor->registerVotes(nodeid,
response, updates, disconnect,
273 std::vector<avalanche::VoteItemUpdate> &updates) {
276 return m_processor->registerVotes(nodeid,
response, updates, disconnect,
280 void setArg(std::string key,
const std::string &value) {
283 m_overridden_args.emplace(std::move(key));
287 return m_processor->addToReconcile(item);
291struct BlockProvider {
292 AvalancheTestingSetup *fixture;
295 BlockProvider(AvalancheTestingSetup *_fixture)
296 : fixture(_fixture), invType(
MSG_BLOCK) {}
299 CBlock block = fixture->CreateAndProcessBlock({}, CScript());
303 return Assert(fixture->m_node.chainman)
304 ->m_blockman.LookupBlockIndex(blockHash);
311 std::vector<Vote> buildVotesForItems(uint32_t
error,
312 std::vector<CBlockIndex *> &&items) {
313 size_t numItems = items.
size();
315 std::vector<Vote> votes;
316 votes.reserve(numItems);
321 votes.emplace_back(
error, item->GetBlockHash());
329 pindex->nStatus = pindex->nStatus.withFailed();
333 return std::get<const CBlockIndex *>(item);
337struct ProofProvider {
338 AvalancheTestingSetup *fixture;
341 ProofProvider(AvalancheTestingSetup *_fixture)
345 ProofRef proof = fixture->GetProof();
353 return proof->
getId();
356 std::vector<Vote> buildVotesForItems(uint32_t
error,
357 std::vector<ProofRef> &&items) {
358 size_t numItems = items.
size();
360 std::vector<Vote> votes;
361 votes.reserve(numItems);
365 for (
auto &item : items) {
366 votes.emplace_back(
error, item->getId());
372 void invalidateItem(
const ProofRef &proof) {
380 return std::get<const ProofRef>(item);
384struct StakeContenderProvider {
385 AvalancheTestingSetup *fixture;
387 std::vector<avalanche::VoteItemUpdate> updates;
390 StakeContenderProvider(AvalancheTestingSetup *_fixture)
398 std::vector<CScript> winners;
399 if (!fixture->m_processor->getStakingRewardWinners(
403 const ProofRef proofWinner = fixture->GetProof();
405 fixture->m_processor->setStakingRewardWinners(chaintip, payouts);
409 const ProofRef proof = fixture->GetProof();
413 fixture->m_processor->withPeerManager(
420 fixture->m_processor->acceptStakeContender(contenderId);
423 fixture->m_processor->getStakeContenderStatus(contenderId) == 0);
432 buildVotesForItems(uint32_t
error, std::vector<StakeContenderId> &&items) {
433 size_t numItems = items.
size();
435 std::vector<Vote> votes;
436 votes.reserve(numItems);
439 std::sort(items.begin(), items.end(),
443 for (
auto &item : items) {
444 votes.emplace_back(
error, item);
451 fixture->m_processor->rejectStakeContender(contenderId);
459 AvalancheTest::removeVoteRecord(*(fixture->m_processor),
464 return std::get<const StakeContenderId>(item);
469 AvalancheTestingSetup *fixture;
471 std::vector<avalanche::VoteItemUpdate> updates;
474 TxProvider(AvalancheTestingSetup *_fixture)
475 : fixture(_fixture), invType(
MSG_TX) {}
485 TestMemPoolEntryHelper mempoolEntryHelper;
486 auto entry = mempoolEntryHelper.Fee(1000 *
SATOSHI).FromTx(tx);
502 std::vector<Vote> buildVotesForItems(uint32_t
error,
503 std::vector<CTransactionRef> &&items) {
504 size_t numItems = items.
size();
506 std::vector<Vote> votes;
507 votes.reserve(numItems);
510 std::sort(items.begin(), items.end(),
512 return lhs->GetId() < rhs->GetId();
514 for (
auto &item : items) {
515 votes.emplace_back(
error, item->GetId());
531 return std::get<const CTransactionRef>(item);
537BOOST_FIXTURE_TEST_SUITE(processor_tests, AvalancheTestingSetup)
541 StakeContenderProvider, TxProvider>;
543 boost::mpl::list<BlockProvider, ProofProvider, TxProvider>;
552 std::set<VoteStatus> status{
553 VoteStatus::Invalid, VoteStatus::Rejected, VoteStatus::Accepted,
554 VoteStatus::Finalized, VoteStatus::Stale,
557 auto item = provider.buildVoteItem();
559 for (
auto s : status) {
582 auto item = provider.buildVoteItem();
583 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);
613 m_processor->setRecentlyFinalized(finalizeItemId);
620 auto finalizeNewItem = [&]() {
621 auto anotherItem = provider.buildVoteItem();
623 auto anotherItemId = provider.getVoteItemId(anotherItem);
626 AvalancheTest::addVoteRecord(*m_processor, anotherVoteItem, voteRecord);
627 finalize(anotherItemId);
647 AvalancheTest::setFinalizationTip(*m_processor, chaintip);
660 auto item =
decltype(provider.buildVoteItem())();
667 item = provider.buildVoteItem();
678 auto itemZero =
decltype(provider.buildVoteItem())();
691 auto item = provider.buildVoteItem();
701 const uint32_t invType = provider.invType;
703 auto item = provider.buildVoteItem();
704 auto itemid = provider.getVoteItemId(item);
707 auto avanodes = ConnectNodes();
715 auto invs = getInvsForNextPoll();
723 int nextNodeIndex = 0;
724 std::vector<avalanche::VoteItemUpdate> updates;
725 auto registerNewVote = [&](
const Response &resp) {
727 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
733 for (
int i = 0; i < 6; i++) {
734 registerNewVote(next(resp));
741 resp = {getRound(), 0, {
Vote(-1, itemid)}};
742 registerNewVote(next(resp));
747 resp = {getRound(), 0, {
Vote(0, itemid)}};
748 for (
int i = 1; i < 7; i++) {
749 registerNewVote(next(resp));
756 resp = {getRound(), 0, {
Vote(-1, itemid)}};
757 registerNewVote(next(resp));
761 registerNewVote(next(resp));
766 resp = {getRound(), 0, {
Vote(0, itemid)}};
767 for (
int i = 2; i < 8; i++) {
768 registerNewVote(next(resp));
776 registerNewVote(next(resp));
783 invs = getInvsForNextPoll();
789 registerNewVote(next(resp));
791 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
792 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
795 invs = getInvsForNextPoll();
799 item = provider.buildVoteItem();
800 itemid = provider.getVoteItemId(item);
804 invs = getInvsForNextPoll();
809 resp = {getRound(), 0, {
Vote(1, itemid)}};
810 for (
int i = 0; i < 6; i++) {
811 registerNewVote(next(resp));
817 registerNewVote(next(resp));
820 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
821 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Rejected);
825 registerNewVote(next(resp));
831 invs = getInvsForNextPoll();
837 registerNewVote(next(resp));
840 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
841 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Invalid);
844 invs = getInvsForNextPoll();
850 const uint32_t invType = provider.invType;
852 auto itemA = provider.buildVoteItem();
853 auto itemidA = provider.getVoteItemId(itemA);
855 auto itemB = provider.buildVoteItem();
856 auto itemidB = provider.getVoteItemId(itemB);
859 auto avanodes = ConnectNodes();
867 auto invs = getInvsForNextPoll();
872 uint64_t round = getRound();
874 std::vector<avalanche::VoteItemUpdate> updates;
876 {round, 0, {
Vote(0, itemidA)}}, updates));
880 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
883 invs = getInvsForNextPoll();
887 for (
size_t i = 0; i < invs.size(); i++) {
893 for (
int i = 0; i < 4; i++) {
894 NodeId nodeid = getSuitableNodeToQuery();
896 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
902 NodeId nodeid = getSuitableNodeToQuery();
904 BOOST_CHECK(registerVotes(nodeid, next(resp), updates));
910 NodeId firstNodeid = getSuitableNodeToQuery();
912 NodeId secondNodeid = getSuitableNodeToQuery();
918 BOOST_CHECK(registerVotes(firstNodeid, next(resp), updates));
920 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemA);
921 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
924 invs = getInvsForNextPoll();
930 BOOST_CHECK(registerVotes(secondNodeid, resp, updates));
932 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == itemB);
933 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Finalized);
936 invs = getInvsForNextPoll();
942 const uint32_t invType = provider.invType;
944 auto item = provider.buildVoteItem();
945 auto itemid = provider.getVoteItemId(item);
952 std::set<NodeId> avanodeIds;
953 auto avanodes = ConnectNodes();
954 for (
auto avanode : avanodes) {
956 avanodeIds.insert(avanode->GetId());
959 auto getSelectedAvanodeId = [&]() {
960 NodeId avanodeid = getSuitableNodeToQuery();
961 BOOST_CHECK(avanodeIds.find(avanodeid) != avanodeIds.end());
966 NodeId avanodeid = getSelectedAvanodeId();
970 auto invs = getInvsForNextPoll();
975 std::set<NodeId> unselectedNodeids = avanodeIds;
976 unselectedNodeids.erase(avanodeid);
977 const size_t remainingNodeIds = unselectedNodeids.size();
979 uint64_t round = getRound();
980 for (
size_t i = 0; i < remainingNodeIds; i++) {
985 NodeId nodeid = getSuitableNodeToQuery();
986 BOOST_CHECK(unselectedNodeids.find(nodeid) != avanodeIds.end());
987 unselectedNodeids.erase(nodeid);
997 std::vector<avalanche::VoteItemUpdate> updates;
998 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1005 auto checkRegisterVotesError = [&](
NodeId nodeid,
1007 const std::string &expectedError) {
1015 checkRegisterVotesError(avanodeid, next(resp),
"unexpected-ava-response");
1024 resp = {round, 0, {
Vote(0, itemid),
Vote(0, itemid)}};
1026 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
1030 resp = {getRound(), 0, {}};
1032 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-size");
1036 resp = {getRound(), 0, {
Vote()}};
1038 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1045 invs = getInvsForNextPoll();
1048 item = provider.buildVoteItem();
1049 itemid = provider.getVoteItemId(item);
1052 invs = getInvsForNextPoll();
1056 uint64_t queryRound = getRound();
1059 resp = {queryRound + 1, 0, {
Vote()}};
1060 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1062 resp = {queryRound - 1, 0, {
Vote()}};
1063 checkRegisterVotesError(avanodeid, resp,
"unexpected-ava-response");
1067 resp = {queryRound, 0, {
Vote(0, itemid)}};
1068 checkRegisterVotesError(avanodeid + 1234, resp,
"unexpected-ava-response");
1071 resp = {queryRound, 0, {
Vote(0, itemid)}};
1072 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1077 const auto item2 = provider.buildVoteItem();
1080 std::vector<Vote> votes = provider.buildVotesForItems(0, {item, item2});
1081 resp = {getRound(), 0, {votes[1], votes[0]}};
1083 checkRegisterVotesError(avanodeid, resp,
"invalid-ava-response-content");
1087 resp = {getRound(), 0, votes};
1089 BOOST_CHECK(registerVotes(avanodeid, resp, updates));
1096 const uint32_t invType = provider.invType;
1098 auto itemA = provider.buildVoteItem();
1099 auto itemB = provider.buildVoteItem();
1101 auto avanodes = ConnectNodes();
1102 int nextNodeIndex = 0;
1105 std::vector<Vote> votes = provider.buildVotesForItems(0, {itemA, itemB});
1111 auto invs = getInvsForNextPoll();
1113 for (
size_t i = 0; i < invs.size(); i++) {
1119 provider.invalidateItem(itemB);
1121 Response goodResp{getRound(), 0, {
Vote(0, provider.getVoteItemId(itemA))}};
1122 std::vector<avalanche::VoteItemUpdate> updates;
1125 registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1126 goodResp, updates));
1130 invs = getInvsForNextPoll();
1133 BOOST_CHECK(invs[0].hash == goodResp.GetVotes()[0].GetHash());
1136 Response badResp{getRound(), 0, votes};
1140 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1141 badResp, updates,
error));
1145 votes = provider.buildVotesForItems(1, {itemA});
1146 auto registerNewVote = [&]() {
1147 Response resp = {getRound(), 0, votes};
1149 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1150 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1152 for (
size_t i = 0; i < 4000; i++) {
1154 if (updates.size() > 0 &&
1155 updates[0].getStatus() == VoteStatus::Invalid) {
1161 invs = getInvsForNextPoll();
1165 badResp =
Response(getRound(), 0, votes);
1168 !registerVotes(avanodes[nextNodeIndex++ % avanodes.size()]->GetId(),
1169 badResp, updates,
error));
1173BOOST_TEST_DECORATOR(*boost::unit_test::timeout(60))
1178 auto queryTimeDuration = std::chrono::milliseconds(10);
1179 setArg(
"-avatimeout",
ToString(queryTimeDuration.count()));
1182 m_processor = Processor::MakeProcessor(
1186 const auto item = provider.buildVoteItem();
1187 const auto itemid = provider.getVoteItemId(item);
1197 for (
int i = 0; i < 10; i++) {
1199 avanodeid = getSuitableNodeToQuery();
1201 auto start = Now<SteadyMilliseconds>();
1205 std::this_thread::sleep_for(std::chrono::milliseconds(1));
1208 std::vector<avalanche::VoteItemUpdate> updates;
1209 bool ret = registerVotes(avanodeid, next(resp), updates);
1210 if (Now<SteadyMilliseconds>() > start + queryTimeDuration) {
1221 avanodeid = getSuitableNodeToQuery();
1225 std::this_thread::sleep_for(queryTimeDuration);
1227 BOOST_CHECK(!registerVotes(avanodeid, next(resp), updates));
1233 const uint32_t invType = provider.invType;
1236 auto proof = GetProof();
1240 std::array<CNode *, AVALANCHE_MAX_INFLIGHT_POLL + 1> nodes;
1241 for (
auto &n : nodes) {
1247 const auto item = provider.buildVoteItem();
1248 const auto itemid = provider.getVoteItemId(item);
1252 std::map<NodeId, uint64_t> node_round_map;
1254 NodeId nodeid = getSuitableNodeToQuery();
1255 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1256 node_round_map.insert(std::pair<NodeId, uint64_t>(nodeid, getRound()));
1257 auto invs = getInvsForNextPoll();
1265 auto suitablenodeid = getSuitableNodeToQuery();
1267 auto invs = getInvsForNextPoll();
1273 auto it = node_round_map.begin();
1275 std::vector<avalanche::VoteItemUpdate> updates;
1276 BOOST_CHECK(registerVotes(it->first, resp, updates));
1277 node_round_map.erase(it);
1279 invs = getInvsForNextPoll();
1286 std::vector<VoteItemUpdate> updates;
1288 CBlock block = CreateAndProcessBlock({}, CScript());
1294 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1298 auto avanodes = ConnectNodes();
1307 uint64_t round = getRound();
1311 for (
size_t i = 0; i < avanodes.size(); i++) {
1313 BOOST_CHECK(registerVotes(avanodes[i]->GetId(), next(resp), updates));
1317 const NodeId firstNodeId = getSuitableNodeToQuery();
1318 std::map<NodeId, uint64_t> node_round_map;
1320 for (
size_t i = 0; i < avanodes.size(); i++) {
1321 NodeId nodeid = getSuitableNodeToQuery();
1322 BOOST_CHECK(node_round_map.find(nodeid) == node_round_map.end());
1323 node_round_map[nodeid] = getRound();
1329 auto confidence = m_processor->getConfidence(pindex);
1330 BOOST_REQUIRE(confidence > 0);
1332 for (
auto &[nodeid, r] : node_round_map) {
1333 if (nodeid == firstNodeId) {
1340 registerVotes(nodeid, {r, 0, {
Vote(0, blockHash)}}, updates));
1345 registerVotes(firstNodeId, {round, 0, {
Vote(0, blockHash)}}, updates));
1352 CBlock block = CreateAndProcessBlock({}, CScript());
1358 Assert(
m_node.chainman)->m_blockman.LookupBlockIndex(blockHash);
1365 std::chrono::steady_clock::time_point start,
stop;
1375 auto avanodes = ConnectNodes();
1378 NodeId nodeid = getSuitableNodeToQuery();
1379 BOOST_CHECK_NE(nodeid,
NO_NODE);
1382 uint64_t queryRound = getRound();
1386 for (
int i = 0; i < 60 * 1000; i++) {
1390 if (getRound() == queryRound + avanodes.size()) {
1399 uint64_t responseRound = getRound();
1400 auto queryTime = Now<SteadyMilliseconds>() + std::chrono::milliseconds(100);
1402 std::vector<VoteItemUpdate> updates;
1404 BOOST_CHECK(registerVotes(nodeid, {queryRound, 100, {
Vote(0, blockHash)}},
1407 for (
int i = 0; i < 10000; i++) {
1410 if (getRound() != responseRound) {
1411 BOOST_CHECK(Now<SteadyMilliseconds>() >= queryTime);
1430 schedulerThread.join();
1435 std::chrono::steady_clock::time_point start,
stop;
1437 std::thread schedulerThread;
1447 m_processor.reset();
1454 schedulerThread.join();
1461 auto addProofToReconcile = [&](uint32_t proofScore) {
1471 auto proof = addProofToReconcile(++score);
1473 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1482 for (
size_t i = 0; i < 10; i++) {
1483 auto proof = addProofToReconcile(++score);
1485 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1490 lastProofId = proof->
getId();
1493 for (
size_t i = 0; i < 10; i++) {
1494 auto proof = addProofToReconcile(--score);
1496 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1504 auto proof = addProofToReconcile(--score);
1505 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
1506 for (
auto &inv : invs) {
1507 BOOST_CHECK_NE(inv.hash, proof->
getId());
1513 setArg(
"-avaproofstakeutxoconfirmations",
"2");
1514 setArg(
"-avalancheconflictingproofcooldown",
"0");
1528 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
1529 coins.
AddCoin(conflictingOutpoint,
1532 coins.
AddCoin(immatureOutpoint,
1537 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
1538 uint32_t height = 10) {
1545 auto conflictingProof = buildProof(conflictingOutpoint, 1);
1546 auto validProof = buildProof(conflictingOutpoint, 2);
1547 auto immatureProof = buildProof(immatureOutpoint, 3, 100);
1549 BOOST_CHECK(!m_processor->isAccepted(conflictingProof));
1550 BOOST_CHECK(!m_processor->isAccepted(validProof));
1551 BOOST_CHECK(!m_processor->isAccepted(immatureProof));
1557 BOOST_CHECK(!m_processor->addToReconcile(conflictingProof));
1558 BOOST_CHECK(!m_processor->addToReconcile(validProof));
1559 BOOST_CHECK(!m_processor->addToReconcile(immatureProof));
1571 BOOST_CHECK(m_processor->addToReconcile(conflictingProof));
1572 BOOST_CHECK(!m_processor->isAccepted(conflictingProof));
1573 BOOST_CHECK(!m_processor->isAccepted(validProof));
1574 BOOST_CHECK(!m_processor->isAccepted(immatureProof));
1579 BOOST_CHECK(m_processor->addToReconcile(validProof));
1580 BOOST_CHECK(!m_processor->isAccepted(conflictingProof));
1582 BOOST_CHECK(!m_processor->isAccepted(immatureProof));
1587 BOOST_CHECK(!m_processor->addToReconcile(immatureProof));
1588 BOOST_CHECK(!m_processor->isAccepted(conflictingProof));
1590 BOOST_CHECK(!m_processor->isAccepted(immatureProof));
1598 int minStake = 400'000'000;
1599 setArg(
"-avaminquorumstake",
ToString(minStake));
1600 setArg(
"-avaminquorumconnectedstakeratio",
"0.5");
1604 uint32_t minScore = Proof::amountToScore(minStake * currency.baseunit);
1612 setArg(
"-avaproof", localProof->ToHex());
1616 m_processor = Processor::MakeProcessor(
1621 BOOST_CHECK(m_processor->getLocalProof() !=
nullptr);
1623 localProof->getId());
1626 AvalancheTest::getMinQuorumConnectedScoreRatio(*m_processor), 0.5);
1647 for (
NodeId id = 0;
id < 8;
id++) {
1649 pm.
addNode(
id, m_processor->getLocalProof()->getId());
1665 const int64_t tipTime =
1669 const Amount amount = (int64_t(minScore / 4) *
COIN) / 100;
1670 const int height = 100;
1671 const bool isCoinbase =
false;
1678 height, isCoinbase),
1683 auto proof2 = pb.
build();
1694 pm.
addNode(8, proof2->getId());
1713 m_processor->withPeerManager(
1719 pm.
addNode(7, m_processor->getLocalProof()->getId());
1724 auto spendProofUtxo = [&](
ProofRef proof) {
1737 for (int64_t i = 0; i < 6; i++) {
1739 CreateAndProcessBlock({}, CScript());
1743 ->GetMedianTimePast(),
1744 proof2->getExpirationTime());
1755 spendProofUtxo(proof1);
1762 spendProofUtxo(m_processor->getLocalProof());
1774 const std::vector<std::tuple<std::string, std::string, std::string, bool>>
1777 {
"",
"",
"",
false},
1778 {
"-1",
"-1",
"-1",
false},
1781 {
"-1",
"0",
"0",
false},
1782 {
"-0.01",
"0",
"0",
false},
1783 {
"21000000000000.01",
"0",
"0",
false},
1786 {
"0",
"-1",
"0",
false},
1787 {
"0",
"1.1",
"0",
false},
1790 {
"0",
"0",
"-1",
false},
1793 {
"0",
"0",
"0",
true},
1794 {
"0.00",
"0",
"0",
true},
1795 {
"0.01",
"0",
"0",
true},
1796 {
"1",
"0.1",
"0",
true},
1797 {
"10",
"0.5",
"0",
true},
1798 {
"10",
"1",
"0",
true},
1799 {
"21000000000000.00",
"0",
"0",
true},
1800 {
"0",
"0",
"1",
true},
1801 {
"0",
"0",
"100",
true},
1806 for (
const auto &[stake, stakeRatio, numProofsMessages, success] :
1808 setArg(
"-avaminquorumstake", stake);
1809 setArg(
"-avaminquorumconnectedstakeratio", stakeRatio);
1810 setArg(
"-avaminavaproofsnodecount", numProofsMessages);
1813 std::unique_ptr<Processor> processor = Processor::MakeProcessor(
1833 auto checkMinAvaproofsMessages = [&](int64_t minAvaproofsMessages) {
1834 setArg(
"-avaminavaproofsnodecount",
ToString(minAvaproofsMessages));
1837 auto processor = Processor::MakeProcessor(
1841 auto addNode = [&](
NodeId nodeid) {
1854 for (
NodeId id = 100;
id < 108;
id++) {
1859 minAvaproofsMessages <= 0);
1861 for (int64_t i = 0; i < minAvaproofsMessages - 1; i++) {
1864 processor->avaproofsSent(i);
1868 processor->avaproofsSent(i);
1874 addNode(minAvaproofsMessages);
1875 processor->avaproofsSent(minAvaproofsMessages);
1879 AvalancheTest::clearavaproofsNodeCounter(*processor);
1883 checkMinAvaproofsMessages(0);
1884 checkMinAvaproofsMessages(1);
1885 checkMinAvaproofsMessages(10);
1886 checkMinAvaproofsMessages(100);
1891 setArg(
"-avastalevotethreshold",
1893 setArg(
"-avastalevotefactor",
"2");
1895 const std::vector<std::tuple<int, int>> testCases = {
1902 m_processor = Processor::MakeProcessor(
1911 const uint32_t invType = provider.invType;
1913 const auto item = provider.buildVoteItem();
1914 const auto itemid = provider.getVoteItemId(item);
1917 auto avanodes = ConnectNodes();
1918 int nextNodeIndex = 0;
1920 std::vector<avalanche::VoteItemUpdate> updates;
1921 for (
const auto &[numYesVotes, numNeutralVotes] : testCases) {
1924 auto invs = getInvsForNextPoll();
1931 auto registerNewVote = [&](
const Response &resp) {
1933 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
1934 BOOST_CHECK(registerVotes(nodeid, resp, updates));
1938 for (
int i = 0; i < numYesVotes; i++) {
1940 registerNewVote(next(resp));
1943 i >= 6 ? i - 5 : 0);
1948 for (
int i = 0; i < numNeutralVotes; i++) {
1950 registerNewVote(next(resp));
1955 invs = getInvsForNextPoll();
1962 registerNewVote(next(resp));
1964 BOOST_CHECK(provider.fromAnyVoteItem(updates[0].getVoteItem()) == item);
1965 BOOST_CHECK(updates[0].getStatus() == VoteStatus::Stale);
1968 invs = getInvsForNextPoll();
1974 BlockProvider provider(
this);
1978 std::vector<CBlockIndex *> blockIndexes;
1982 blockIndexes.push_back(pindex);
1985 auto invs = getInvsForNextPoll();
1997 std::vector<Vote> votes;
2000 BlockHash blockhash = blockIndexes[i - 1]->GetBlockHash();
2001 votes.emplace_back(blockhash == eleventhBlockHash ? 0 : -1, blockhash);
2004 auto avanodes = ConnectNodes();
2005 int nextNodeIndex = 0;
2007 std::vector<avalanche::VoteItemUpdate> updates;
2008 auto registerNewVote = [&]() {
2009 Response resp = {getRound(), 0, votes};
2011 auto nodeid = avanodes[nextNodeIndex++ % avanodes.size()]->GetId();
2012 BOOST_CHECK(registerVotes(nodeid, resp, updates));
2018 bool eleventhBlockFinalized =
false;
2019 for (
size_t i = 0; i < 10000 && !eleventhBlockFinalized; i++) {
2022 for (
auto &update : updates) {
2023 if (update.getStatus() == VoteStatus::Finalized &&
2024 provider.fromAnyVoteItem(update.getVoteItem())
2025 ->GetBlockHash() == eleventhBlockHash) {
2026 eleventhBlockFinalized =
true;
2037 invs = getInvsForNextPoll();
2039 for (
size_t i = 0; i < 10; i++) {
2053 auto &activeChainstate =
m_node.chainman->ActiveChainstate();
2055 activeChainstate.InvalidateBlock(state, tip);
2058 CBlock altblock = CreateAndProcessBlock({}, CScript() <<
OP_TRUE);
2061 ->m_blockman.LookupBlockIndex(altblock.
GetHash()));
2069 activeChainstate.ResetBlockFailureFlags(tip);
2071 activeChainstate.ActivateBestChain(state);
2075 invs = getInvsForNextPoll();
2082 for (
auto &inv : invs) {
2083 votes.emplace_back(inv.hash == tiphash ? 0 : -1, inv.hash);
2086 bool tipFinalized =
false;
2087 for (
size_t i = 0; i < 10000 && !tipFinalized; i++) {
2090 for (
auto &update : updates) {
2091 if (update.getStatus() == VoteStatus::Finalized &&
2092 provider.fromAnyVoteItem(update.getVoteItem())
2093 ->GetBlockHash() == tiphash) {
2094 tipFinalized =
true;
2103 invs = getInvsForNextPoll();
2111 BlockHash alttiphash = alttip->GetBlockHash();
2112 votes = {{1, alttiphash}};
2114 bool alttipInvalidated =
false;
2115 for (
size_t i = 0; i < 10000 && !alttipInvalidated; i++) {
2118 for (
auto &update : updates) {
2119 if (update.getStatus() == VoteStatus::Invalid &&
2120 provider.fromAnyVoteItem(update.getVoteItem())
2121 ->GetBlockHash() == alttiphash) {
2122 alttipInvalidated =
true;
2127 invs = getInvsForNextPoll();
2138 const int numberElementsEachType = 100;
2141 std::vector<ProofRef> proofs;
2142 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2146 proofs.emplace_back(std::move(proof));
2148 Shuffle(proofs.begin(), proofs.end(), rng);
2150 std::vector<CBlockIndex> indexes;
2151 for (
size_t i = 1; i <= numberElementsEachType; i++) {
2154 indexes.emplace_back(std::move(index));
2156 Shuffle(indexes.begin(), indexes.end(), rng);
2158 auto allItems = std::make_tuple(std::move(proofs), std::move(indexes));
2159 static const size_t numTypes = std::tuple_size<
decltype(allItems)>::value;
2165 for (
size_t i = 0; i < numberElementsEachType; i++) {
2167 const size_t firstType = rng.
randrange(numTypes);
2169 for (
size_t j = 0; j < numTypes; j++) {
2170 switch ((firstType + j) % numTypes) {
2173 writeView->insert(std::make_pair(
2174 std::get<0>(allItems)[i],
VoteRecord(
true)));
2178 writeView->insert(std::make_pair(
2179 &std::get<1>(allItems)[i],
VoteRecord(
true)));
2190 auto readView = voteMap.getReadView();
2191 auto it = readView.begin();
2194 uint32_t lastScore = std::numeric_limits<uint32_t>::max();
2195 for (
size_t i = 0; i < numberElementsEachType; i++) {
2196 BOOST_CHECK(std::holds_alternative<const ProofRef>(it->first));
2198 uint32_t currentScore =
2199 std::get<const ProofRef>(it->first)->getScore();
2200 BOOST_CHECK_LT(currentScore, lastScore);
2201 lastScore = currentScore;
2209 for (
size_t i = 0; i < numberElementsEachType; i++) {
2210 BOOST_CHECK(std::holds_alternative<const CBlockIndex *>(it->first));
2213 std::get<const CBlockIndex *>(it->first)->nChainWork;
2215 lastWork = currentWork;
2228 const auto block = std::make_shared<const CBlock>(
2229 this->CreateBlock({}, CScript(), chainstate));
2246 BOOST_CHECK(AvalancheTest::getInvsForNextPoll(*m_processor).empty());
2247 BOOST_CHECK(!m_processor->isAccepted(blockindex));
2255 auto invs = AvalancheTest::getInvsForNextPoll(*m_processor);
2268 auto now = GetTime<std::chrono::seconds>();
2274 std::vector<CScript> winners;
2276 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2279 BOOST_CHECK(!m_processor->computeStakingReward(
nullptr));
2280 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2285 prevBlock.
nTime = now.count();
2288 BOOST_CHECK(!m_processor->computeStakingReward(&prevBlock));
2289 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2292 size_t numProofs = 10;
2293 std::vector<ProofRef> proofs;
2294 proofs.reserve(numProofs);
2295 for (
size_t i = 0; i < numProofs; i++) {
2299 auto proof = GetProof(payoutScript);
2305 return pm.setFinalized(peer.peerid);
2309 proofs.emplace_back(std::move(proof));
2315 BOOST_CHECK(!m_processor->computeStakingReward(&prevBlock));
2316 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2319 auto winnerExists = [&](
const CScript &expectedWinner) {
2320 const std::string winnerString =
FormatScript(expectedWinner);
2322 for (
const ProofRef &proof : proofs) {
2333 prevBlock.
nTime = now.count();
2336 BOOST_CHECK(m_processor->computeStakingReward(&prevBlock));
2337 BOOST_CHECK(m_processor->getStakingRewardWinners(prevBlockHash, winners));
2341 BOOST_CHECK(m_processor->computeStakingReward(&prevBlock));
2342 BOOST_CHECK(m_processor->getStakingRewardWinners(prevBlockHash, winners));
2348 prevBlockHigh.
phashBlock = &prevBlockHashHigh;
2350 BOOST_CHECK(m_processor->computeStakingReward(&prevBlockHigh));
2352 m_processor->getStakingRewardWinners(prevBlockHashHigh, winners));
2356 BOOST_CHECK(m_processor->getStakingRewardWinners(prevBlockHash, winners));
2360 m_processor->cleanupStakingRewards(101);
2363 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2367 m_processor->getStakingRewardWinners(prevBlockHashHigh, winners));
2371 BOOST_CHECK(m_processor->computeStakingReward(&prevBlock));
2372 BOOST_CHECK(m_processor->getStakingRewardWinners(prevBlockHash, winners));
2376 m_processor->cleanupStakingRewards(200);
2379 BOOST_CHECK(!m_processor->getStakingRewardWinners(prevBlockHash, winners));
2381 !m_processor->getStakingRewardWinners(prevBlockHashHigh, winners));
2393 Assert(
m_node.chainman)->ActiveChainstate().CoinsTip();
2399 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence,
2407 auto localProof = buildProof(outpoint, 1, 100);
2410 setArg(
"-avaproof", localProof->ToHex());
2411 setArg(
"-avalancheconflictingproofcooldown",
"0");
2412 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2413 setArg(
"-avaproofstakeutxoconfirmations",
"3");
2417 m_processor = Processor::MakeProcessor(
2422 localProof->getId());
2424 auto checkLocalProofState =
2425 [&](
const bool boundToPeer,
2429 return pm.isBoundToPeer(localProof->getId());
2432 BOOST_CHECK_MESSAGE(
2433 m_processor->getLocalProofRegistrationState().GetResult() ==
2435 m_processor->getLocalProofRegistrationState().ToString());
2442 AvalancheTest::updatedBlockTip(*m_processor);
2446 AvalancheTest::setLocalProofShareable(*m_processor,
true);
2448 AvalancheTest::updatedBlockTip(*m_processor);
2449 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2453 AvalancheTest::updatedBlockTip(*m_processor);
2454 checkLocalProofState(
false, ProofRegistrationResult::IMMATURE);
2458 AvalancheTest::updatedBlockTip(*m_processor);
2462 auto conflictingProof = buildProof(outpoint, 2, 100);
2468 AvalancheTest::updatedBlockTip(*m_processor);
2469 checkLocalProofState(
false, ProofRegistrationResult::CONFLICTING);
2473 setArg(
"-avalancheconflictingproofcooldown",
"0");
2474 setArg(
"-avalanchepeerreplacementcooldown",
"0");
2494 auto buildProof = [&](
const COutPoint &outpoint, uint64_t sequence) {
2501 auto proof = buildProof(outpoint, 1);
2505 BOOST_CHECK(!m_processor->reconcileOrFinalize(proof));
2515 BOOST_CHECK(m_processor->reconcileOrFinalize(proof));
2517 BOOST_CHECK(!m_processor->reconcileOrFinalize(proof));
2520 AvalancheTest::addProofToRecentfinalized(*m_processor, proof->
getId());
2522 BOOST_CHECK(m_processor->reconcileOrFinalize(proof));
2527 return peer.hasFinalized;
2534 auto betterProof = buildProof(outpoint, 2);
2538 BOOST_CHECK(!m_processor->reconcileOrFinalize(betterProof));
2550 BOOST_CHECK(!m_processor->reconcileOrFinalize(proof));
2552 BOOST_CHECK(m_processor->reconcileOrFinalize(betterProof));
2556 setArg(
"-avalanchestakingpreconsensus",
"1");
2558 m_processor = Processor::MakeProcessor(
2564 auto now = GetTime<std::chrono::seconds>();
2573 const ProofId proofid1 = proof1->getId();
2578 const ProofId proofid2 = proof2->getId();
2602 for (
NodeId n = 0; n < 8; n++) {
2607 return pm.setFinalized(peer.peerid);
2616 CBlock block = CreateAndProcessBlock({}, CScript());
2619 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2620 AvalancheTest::updatedBlockTip(*m_processor);
2624 BOOST_CHECK(m_processor->computeStakingReward(chaintip));
2626 std::vector<CScript> winners;
2630 BOOST_CHECK(winners[0] == proof2->getPayoutScript());
2658 m_processor->cleanupStakingRewards(chaintip->
nHeight);
2674 m_processor->setStakingRewardWinners(
2675 chaintip, {proof1->getPayoutScript(), proof2->getPayoutScript()});
2686 m_processor->withPeerManager(
2692 const ProofId proofid3 = proof3->getId();
2695 for (
NodeId n = 0; n < 8; n++) {
2701 block = CreateAndProcessBlock({}, CScript());
2704 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2705 AvalancheTest::updatedBlockTip(*m_processor);
2706 m_processor->cleanupStakingRewards(chaintip->
nHeight);
2729 m_processor->withPeerManager(
2733 size_t numProofs = 8;
2734 std::vector<ProofRef> proofs;
2735 proofs.reserve(numProofs);
2736 for (
size_t i = 0; i < numProofs; i++) {
2745 return pm.setFinalized(peer.peerid);
2748 proofs.emplace_back(std::move(proof));
2753 const ProofId proofid = proofs[0]->getId();
2754 for (
NodeId n = 0; n < 8; n++) {
2764 std::vector<CScript> winners;
2765 for (
int attempt = 0; attempt < 10; attempt++) {
2767 block = CreateAndProcessBlock({}, CScript());
2770 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2771 AvalancheTest::updatedBlockTip(*m_processor);
2775 BOOST_CHECK(m_processor->computeStakingReward(chaintip));
2777 chaintip->GetBlockHash(), winners));
2778 if (winners.size() == 8) {
2786 size_t numAccepted = 0;
2787 for (
const auto &proof : proofs) {
2791 if (m_processor->getStakeContenderStatus(contender) == 0) {
2793 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2801 block = CreateAndProcessBlock({}, CScript());
2804 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2809 m_processor->withPeerManager(
2811 AvalancheTest::updatedBlockTip(*m_processor);
2815 BOOST_CHECK(m_processor->computeStakingReward(chaintip));
2820 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2821 bestproof->getPayoutScript()) == winners.end());
2839 block = CreateAndProcessBlock({}, CScript());
2842 ->m_blockman.LookupBlockIndex(block.
GetHash()));
2843 AvalancheTest::updatedBlockTip(*m_processor);
2844 AvalancheTest::setFinalizationTip(*m_processor, chaintip);
2845 m_processor->cleanupStakingRewards(chaintip->
nHeight);
2851 std::unordered_set<ProofRef, SaltedProofHasher> dummy;
2860 BOOST_CHECK(m_processor->computeStakingReward(chaintip));
2865 BOOST_CHECK(std::find(winners.begin(), winners.end(),
2866 bestproof->getPayoutScript()) == winners.end());
2885 auto now = GetTime<std::chrono::seconds>();
2889 auto localWinnerProof =
2891 ProofId localWinnerProofId = localWinnerProof->getId();
2893 localWinnerProof->getId());
2902 for (
NodeId n = 0; n < 8; n++) {
2903 pm.
addNode(n, localWinnerProofId);
2906 return pm.setFinalized(peer.peerid);
2913 chaintip->
nTime = now.count();
2917 BOOST_CHECK(m_processor->computeStakingReward(chaintip));
2919 std::vector<ProofRef> acceptedContenderProofs;
2920 acceptedContenderProofs.push_back(localWinnerProof);
2927 for (
size_t numContenders = 2;
2931 m_processor->withPeerManager(
2937 if (rank <= bestRank) {
2939 acceptedContenderProofs.push_back(proof);
2940 const size_t numAccepted =
2942 acceptedContenderProofs.size());
2943 std::sort(acceptedContenderProofs.begin(),
2944 acceptedContenderProofs.begin() + numAccepted,
2946 const ProofId leftProofId = left->getId();
2947 const ProofId rightProofId = right->getId();
2948 const StakeContenderId leftContenderId(chaintipHash,
2950 const StakeContenderId rightContenderId(chaintipHash,
2952 return RewardRankComparator()(
2954 leftContenderId.ComputeProofRewardRank(
2955 MIN_VALID_PROOF_SCORE),
2956 leftProofId, rightContenderId,
2957 rightContenderId.ComputeProofRewardRank(
2958 MIN_VALID_PROOF_SCORE),
2963 std::vector<StakeContenderId> pollableContenders;
2964 BOOST_CHECK(AvalancheTest::setContenderStatusForLocalWinners(
2965 *m_processor, chaintip, pollableContenders));
2967 pollableContenders.size(),
2972 for (
size_t i = 0; i < std::min(acceptedContenderProofs.size(),
2976 chaintipHash, acceptedContenderProofs[i]->getId());
2978 std::find(pollableContenders.begin(), pollableContenders.end(),
2979 acceptedContenderId) != pollableContenders.end());
2981 m_processor->getStakeContenderStatus(acceptedContenderId), 0);
2985 std::set<StakeContenderId> unacceptedContenderIds(
2986 pollableContenders.begin(), pollableContenders.end());
2987 for (
auto &acceptedContenderProof : acceptedContenderProofs) {
2989 chaintipHash, acceptedContenderProof->getId());
2990 unacceptedContenderIds.erase(acceptedContenderId);
2993 for (
auto cid : unacceptedContenderIds) {
2999 m_processor->getStakeContenderStatus(localWinnerContenderId), 0);
3003BOOST_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.
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 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
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()
@ 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)
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.
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.