Bitcoin ABC  0.26.3
P2P Digital Currency
processor.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2019 The Bitcoin developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include <avalanche/processor.h>
6 
7 #include <avalanche/avalanche.h>
11 #include <avalanche/validation.h>
12 #include <avalanche/voterecord.h>
13 #include <chain.h>
14 #include <common/args.h>
15 #include <key_io.h> // For DecodeSecret
16 #include <net.h>
17 #include <netmessagemaker.h>
19 #include <scheduler.h>
20 #include <util/bitmanip.h>
21 #include <util/moneystr.h>
22 #include <util/time.h>
23 #include <util/translation.h>
24 #include <validation.h>
25 
26 #include <chrono>
27 #include <limits>
28 #include <tuple>
29 
33 static constexpr std::chrono::milliseconds AVALANCHE_TIME_STEP{10};
34 
35 static const std::string AVAPEERS_FILE_NAME{"avapeers.dat"};
36 
37 namespace avalanche {
38 static const uint256 GetVoteItemId(const AnyVoteItem &item) {
39  return std::visit(variant::overloaded{
40  [](const ProofRef &proof) {
41  uint256 id = proof->getId();
42  return id;
43  },
44  [](const CBlockIndex *pindex) {
45  uint256 hash = pindex->GetBlockHash();
46  return hash;
47  },
48  [](const CTransactionRef &tx) {
49  uint256 id = tx->GetId();
50  return id;
51  },
52  },
53  item);
54 }
55 
56 static bool VerifyProof(const Amount &stakeUtxoDustThreshold,
57  const Proof &proof, bilingual_str &error) {
58  ProofValidationState proof_state;
59 
60  if (!proof.verify(stakeUtxoDustThreshold, proof_state)) {
61  switch (proof_state.GetResult()) {
63  error = _("The avalanche proof has no stake.");
64  return false;
66  error = _("The avalanche proof stake is too low.");
67  return false;
69  error = _("The avalanche proof has duplicated stake.");
70  return false;
72  error = _("The avalanche proof has invalid stake signatures.");
73  return false;
75  error = strprintf(
76  _("The avalanche proof has too many utxos (max: %u)."),
78  return false;
79  default:
80  error = _("The avalanche proof is invalid.");
81  return false;
82  }
83  }
84 
85  return true;
86 }
87 
88 static bool VerifyDelegation(const Delegation &dg,
89  const CPubKey &expectedPubKey,
91  DelegationState dg_state;
92 
93  CPubKey auth;
94  if (!dg.verify(dg_state, auth)) {
95  switch (dg_state.GetResult()) {
97  error = _("The avalanche delegation has invalid signatures.");
98  return false;
100  error = _(
101  "The avalanche delegation has too many delegation levels.");
102  return false;
103  default:
104  error = _("The avalanche delegation is invalid.");
105  return false;
106  }
107  }
108 
109  if (auth != expectedPubKey) {
110  error = _(
111  "The avalanche delegation does not match the expected public key.");
112  return false;
113  }
114 
115  return true;
116 }
117 
121 
124 };
125 
129 
130 public:
132 
134 
136  uint64_t mempool_sequence) override {
138  }
139 };
140 
142  CConnman *connmanIn, ChainstateManager &chainmanIn,
143  CTxMemPool *mempoolIn, CScheduler &scheduler,
144  std::unique_ptr<PeerData> peerDataIn, CKey sessionKeyIn,
145  uint32_t minQuorumTotalScoreIn,
146  double minQuorumConnectedScoreRatioIn,
147  int64_t minAvaproofsNodeCountIn,
148  uint32_t staleVoteThresholdIn, uint32_t staleVoteFactorIn,
149  Amount stakeUtxoDustThreshold, bool preConsensus)
150  : avaconfig(std::move(avaconfigIn)), connman(connmanIn),
151  chainman(chainmanIn), mempool(mempoolIn),
152  voteRecords(RWCollection<VoteMap>(VoteMap(VoteMapComparator(mempool)))),
153  round(0), peerManager(std::make_unique<PeerManager>(
154  stakeUtxoDustThreshold, chainman,
155  peerDataIn ? peerDataIn->proof : ProofRef())),
156  peerData(std::move(peerDataIn)), sessionKey(std::move(sessionKeyIn)),
157  minQuorumScore(minQuorumTotalScoreIn),
158  minQuorumConnectedScoreRatio(minQuorumConnectedScoreRatioIn),
159  minAvaproofsNodeCount(minAvaproofsNodeCountIn),
160  staleVoteThreshold(staleVoteThresholdIn),
161  staleVoteFactor(staleVoteFactorIn), m_preConsensus(preConsensus) {
162  // Make sure we get notified of chain state changes.
164  chain.handleNotifications(std::make_shared<NotificationsHandler>(this));
165 
166  scheduler.scheduleEvery(
167  [this]() -> bool {
168  std::unordered_set<ProofRef, SaltedProofHasher> registeredProofs;
170  peerManager->cleanupDanglingProofs(registeredProofs));
171  for (const auto &proof : registeredProofs) {
173  "Promoting previously dangling proof %s\n",
174  proof->getId().ToString());
175  reconcileOrFinalize(proof);
176  }
177  return true;
178  },
179  5min);
180 
181  if (!gArgs.GetBoolArg("-persistavapeers", DEFAULT_PERSIST_AVAPEERS)) {
182  return;
183  }
184 
185  std::unordered_set<ProofRef, SaltedProofHasher> registeredProofs;
186 
187  // Attempt to load the peer file if it exists.
188  const fs::path dumpPath = gArgs.GetDataDirNet() / AVAPEERS_FILE_NAME;
189  WITH_LOCK(cs_peerManager, return peerManager->loadPeersFromFile(
190  dumpPath, registeredProofs));
191 
192  // We just loaded the previous finalization status, but make sure to trigger
193  // another round of vote for these proofs to avoid issue if the network
194  // status changed since the peers file was dumped.
195  for (const auto &proof : registeredProofs) {
196  addToReconcile(proof);
197  }
198 
199  LogPrint(BCLog::AVALANCHE, "Loaded %d peers from the %s file\n",
200  registeredProofs.size(), PathToString(dumpPath));
201 }
202 
205  stopEventLoop();
206 
207  if (!gArgs.GetBoolArg("-persistavapeers", DEFAULT_PERSIST_AVAPEERS)) {
208  return;
209  }
210 
212  // Discard the status output: if it fails we want to continue normally.
213  peerManager->dumpPeersToFile(gArgs.GetDataDirNet() / AVAPEERS_FILE_NAME);
214 }
215 
216 std::unique_ptr<Processor>
218  CConnman *connman, ChainstateManager &chainman,
219  CTxMemPool *mempool, CScheduler &scheduler,
220  bilingual_str &error) {
221  std::unique_ptr<PeerData> peerData;
222  CKey masterKey;
224 
225  Amount stakeUtxoDustThreshold = PROOF_DUST_THRESHOLD;
226  if (argsman.IsArgSet("-avaproofstakeutxodustthreshold") &&
227  !ParseMoney(argsman.GetArg("-avaproofstakeutxodustthreshold", ""),
228  stakeUtxoDustThreshold)) {
229  error = _("The avalanche stake utxo dust threshold amount is invalid.");
230  return nullptr;
231  }
232 
233  if (argsman.IsArgSet("-avasessionkey")) {
234  sessionKey = DecodeSecret(argsman.GetArg("-avasessionkey", ""));
235  if (!sessionKey.IsValid()) {
236  error = _("The avalanche session key is invalid.");
237  return nullptr;
238  }
239  } else {
240  // Pick a random key for the session.
241  sessionKey.MakeNewKey(true);
242  }
243 
244  if (argsman.IsArgSet("-avaproof")) {
245  if (!argsman.IsArgSet("-avamasterkey")) {
246  error = _(
247  "The avalanche master key is missing for the avalanche proof.");
248  return nullptr;
249  }
250 
251  masterKey = DecodeSecret(argsman.GetArg("-avamasterkey", ""));
252  if (!masterKey.IsValid()) {
253  error = _("The avalanche master key is invalid.");
254  return nullptr;
255  }
256 
257  auto proof = RCUPtr<Proof>::make();
258  if (!Proof::FromHex(*proof, argsman.GetArg("-avaproof", ""), error)) {
259  // error is set by FromHex
260  return nullptr;
261  }
262 
263  peerData = std::make_unique<PeerData>();
264  peerData->proof = proof;
265  if (!VerifyProof(stakeUtxoDustThreshold, *peerData->proof, error)) {
266  // error is set by VerifyProof
267  return nullptr;
268  }
269 
270  std::unique_ptr<DelegationBuilder> dgb;
271  const CPubKey &masterPubKey = masterKey.GetPubKey();
272 
273  if (argsman.IsArgSet("-avadelegation")) {
274  Delegation dg;
275  if (!Delegation::FromHex(dg, argsman.GetArg("-avadelegation", ""),
276  error)) {
277  // error is set by FromHex()
278  return nullptr;
279  }
280 
281  if (dg.getProofId() != peerData->proof->getId()) {
282  error = _("The delegation does not match the proof.");
283  return nullptr;
284  }
285 
286  if (masterPubKey != dg.getDelegatedPubkey()) {
287  error = _(
288  "The master key does not match the delegation public key.");
289  return nullptr;
290  }
291 
292  dgb = std::make_unique<DelegationBuilder>(dg);
293  } else {
294  if (masterPubKey != peerData->proof->getMaster()) {
295  error =
296  _("The master key does not match the proof public key.");
297  return nullptr;
298  }
299 
300  dgb = std::make_unique<DelegationBuilder>(*peerData->proof);
301  }
302 
303  // Generate the delegation to the session key.
304  const CPubKey sessionPubKey = sessionKey.GetPubKey();
305  if (sessionPubKey != masterPubKey) {
306  if (!dgb->addLevel(masterKey, sessionPubKey)) {
307  error = _("Failed to generate a delegation for this session.");
308  return nullptr;
309  }
310  }
311  peerData->delegation = dgb->build();
312 
313  if (!VerifyDelegation(peerData->delegation, sessionPubKey, error)) {
314  // error is set by VerifyDelegation
315  return nullptr;
316  }
317  }
318 
319  const auto queryTimeoutDuration =
320  std::chrono::milliseconds(argsman.GetIntArg(
321  "-avatimeout", AVALANCHE_DEFAULT_QUERY_TIMEOUT.count()));
322 
323  // Determine quorum parameters
325  if (argsman.IsArgSet("-avaminquorumstake") &&
326  !ParseMoney(argsman.GetArg("-avaminquorumstake", ""), minQuorumStake)) {
327  error = _("The avalanche min quorum stake amount is invalid.");
328  return nullptr;
329  }
330 
331  if (!MoneyRange(minQuorumStake)) {
332  error = _("The avalanche min quorum stake amount is out of range.");
333  return nullptr;
334  }
335 
336  double minQuorumConnectedStakeRatio =
338  if (argsman.IsArgSet("-avaminquorumconnectedstakeratio") &&
339  !ParseDouble(argsman.GetArg("-avaminquorumconnectedstakeratio", ""),
340  &minQuorumConnectedStakeRatio)) {
341  error = _("The avalanche min quorum connected stake ratio is invalid.");
342  return nullptr;
343  }
344 
345  if (minQuorumConnectedStakeRatio < 0 || minQuorumConnectedStakeRatio > 1) {
346  error = _(
347  "The avalanche min quorum connected stake ratio is out of range.");
348  return nullptr;
349  }
350 
351  int64_t minAvaproofsNodeCount =
352  argsman.GetIntArg("-avaminavaproofsnodecount",
354  if (minAvaproofsNodeCount < 0) {
355  error = _("The minimum number of node that sent avaproofs message "
356  "should be non-negative");
357  return nullptr;
358  }
359 
360  // Determine voting parameters
361  int64_t staleVoteThreshold = argsman.GetIntArg(
362  "-avastalevotethreshold", AVALANCHE_VOTE_STALE_THRESHOLD);
364  error = strprintf(_("The avalanche stale vote threshold must be "
365  "greater than or equal to %d"),
367  return nullptr;
368  }
369  if (staleVoteThreshold > std::numeric_limits<uint32_t>::max()) {
370  error = strprintf(_("The avalanche stale vote threshold must be less "
371  "than or equal to %d"),
372  std::numeric_limits<uint32_t>::max());
373  return nullptr;
374  }
375 
376  int64_t staleVoteFactor =
377  argsman.GetIntArg("-avastalevotefactor", AVALANCHE_VOTE_STALE_FACTOR);
378  if (staleVoteFactor <= 0) {
379  error = _("The avalanche stale vote factor must be greater than 0");
380  return nullptr;
381  }
382  if (staleVoteFactor > std::numeric_limits<uint32_t>::max()) {
383  error = strprintf(_("The avalanche stale vote factor must be less than "
384  "or equal to %d"),
385  std::numeric_limits<uint32_t>::max());
386  return nullptr;
387  }
388 
389  Config avaconfig(queryTimeoutDuration);
390 
391  // We can't use std::make_unique with a private constructor
392  return std::unique_ptr<Processor>(new Processor(
393  std::move(avaconfig), chain, connman, chainman, mempool, scheduler,
394  std::move(peerData), std::move(sessionKey),
395  Proof::amountToScore(minQuorumStake), minQuorumConnectedStakeRatio,
397  stakeUtxoDustThreshold,
398  argsman.GetBoolArg("-avalanchepreconsensus",
400 }
401 
402 static bool isNull(const AnyVoteItem &item) {
403  return item.valueless_by_exception() ||
404  std::visit([](const auto &item) { return item == nullptr; }, item);
405 };
406 
408  if (isNull(item)) {
409  return false;
410  }
411 
412  if (!isWorthPolling(item)) {
413  return false;
414  }
415 
416  // getLocalAcceptance() takes the voteRecords read lock, so we can't inline
417  // the calls or we get a deadlock.
418  const bool accepted = getLocalAcceptance(item);
419 
420  return voteRecords.getWriteView()
421  ->insert(std::make_pair(item, VoteRecord(accepted)))
422  .second;
423 }
424 
426  if (!proof) {
427  return false;
428  }
429 
430  if (isRecentlyFinalized(proof->getId())) {
431  PeerId peerid;
433  if (peerManager->forPeer(proof->getId(), [&](const Peer &peer) {
434  peerid = peer.peerid;
435  return true;
436  })) {
437  return peerManager->setFinalized(peerid);
438  }
439  }
440 
441  return addToReconcile(proof);
442 }
443 
444 bool Processor::isAccepted(const AnyVoteItem &item) const {
445  if (isNull(item)) {
446  return false;
447  }
448 
449  auto r = voteRecords.getReadView();
450  auto it = r->find(item);
451  if (it == r.end()) {
452  return false;
453  }
454 
455  return it->second.isAccepted();
456 }
457 
458 int Processor::getConfidence(const AnyVoteItem &item) const {
459  if (isNull(item)) {
460  return -1;
461  }
462 
463  auto r = voteRecords.getReadView();
464  auto it = r->find(item);
465  if (it == r.end()) {
466  return -1;
467  }
468 
469  return it->second.getConfidence();
470 }
471 
472 bool Processor::isRecentlyFinalized(const uint256 &itemId) const {
473  return WITH_LOCK(cs_finalizedItems, return finalizedItems.contains(itemId));
474 }
475 
478  finalizedItems.reset();
479 }
480 
481 namespace {
486  class TCPResponse {
487  Response response;
489 
490  public:
491  TCPResponse(Response responseIn, const CKey &key)
492  : response(std::move(responseIn)) {
493  HashWriter hasher{};
494  hasher << response;
495  const uint256 hash = hasher.GetHash();
496 
497  // Now let's sign!
498  if (!key.SignSchnorr(hash, sig)) {
499  sig.fill(0);
500  }
501  }
502 
503  // serialization support
504  SERIALIZE_METHODS(TCPResponse, obj) {
505  READWRITE(obj.response, obj.sig);
506  }
507  };
508 } // namespace
509 
512  pfrom, CNetMsgMaker(pfrom->GetCommonVersion())
514  TCPResponse(std::move(response), sessionKey)));
515 }
516 
518  std::vector<VoteItemUpdate> &updates,
519  int &banscore, std::string &error) {
520  {
521  // Save the time at which we can query again.
523 
524  // FIXME: This will override the time even when we received an old stale
525  // message. This should check that the message is indeed the most up to
526  // date one before updating the time.
527  peerManager->updateNextRequestTime(
528  nodeid, Now<SteadyMilliseconds>() +
529  std::chrono::milliseconds(response.getCooldown()));
530  }
531 
532  std::vector<CInv> invs;
533 
534  {
535  // Check that the query exists. There is a possibility that it has been
536  // deleted if the query timed out, so we don't increase the ban score to
537  // slowly banning nodes for poor networking over time. Banning has to be
538  // handled at callsite to avoid DoS.
539  auto w = queries.getWriteView();
540  auto it = w->find(std::make_tuple(nodeid, response.getRound()));
541  if (it == w.end()) {
542  banscore = 0;
543  error = "unexpected-ava-response";
544  return false;
545  }
546 
547  invs = std::move(it->invs);
548  w->erase(it);
549  }
550 
551  // Verify that the request and the vote are consistent.
552  const std::vector<Vote> &votes = response.GetVotes();
553  size_t size = invs.size();
554  if (votes.size() != size) {
555  banscore = 100;
556  error = "invalid-ava-response-size";
557  return false;
558  }
559 
560  for (size_t i = 0; i < size; i++) {
561  if (invs[i].hash != votes[i].GetHash()) {
562  banscore = 100;
563  error = "invalid-ava-response-content";
564  return false;
565  }
566  }
567 
568  std::map<AnyVoteItem, Vote, VoteMapComparator> responseItems(
570 
571  // At this stage we are certain that invs[i] matches votes[i], so we can use
572  // the inv type to retrieve what is being voted on.
573  for (size_t i = 0; i < size; i++) {
574  auto item = getVoteItemFromInv(invs[i]);
575 
576  if (isNull(item)) {
577  // This should not happen, but just in case...
578  continue;
579  }
580 
581  if (!isWorthPolling(item)) {
582  // There is no point polling this item.
583  continue;
584  }
585 
586  responseItems.insert(std::make_pair(std::move(item), votes[i]));
587  }
588 
589  auto voteRecordsWriteView = voteRecords.getWriteView();
590 
591  // Register votes.
592  for (const auto &p : responseItems) {
593  auto item = p.first;
594  const Vote &v = p.second;
595 
596  auto it = voteRecordsWriteView->find(item);
597  if (it == voteRecordsWriteView.end()) {
598  // We are not voting on that item anymore.
599  continue;
600  }
601 
602  auto &vr = it->second;
603  if (!vr.registerVote(nodeid, v.GetError())) {
604  if (vr.isStale(staleVoteThreshold, staleVoteFactor)) {
605  updates.emplace_back(std::move(item), VoteStatus::Stale);
606 
607  // Just drop stale votes. If we see this item again, we'll
608  // do a new vote.
609  voteRecordsWriteView->erase(it);
610  }
611  // This vote did not provide any extra information, move on.
612  continue;
613  }
614 
615  if (!vr.hasFinalized()) {
616  // This item has not been finalized, so we have nothing more to
617  // do.
618  updates.emplace_back(std::move(item), vr.isAccepted()
621  continue;
622  }
623 
624  // We just finalized a vote. If it is valid, then let the caller
625  // know. Either way, remove the item from the map.
626  updates.emplace_back(std::move(item), vr.isAccepted()
629  voteRecordsWriteView->erase(it);
630  }
631 
632  // FIXME This doesn't belong here as it has nothing to do with vote
633  // registration.
634  for (const auto &update : updates) {
635  if (update.getStatus() != VoteStatus::Finalized &&
636  update.getStatus() != VoteStatus::Invalid) {
637  continue;
638  }
639 
640  const auto &item = update.getVoteItem();
641 
642  if (update.getStatus() == VoteStatus::Finalized) {
643  // Always track finalized items regardless of type. Once finalized
644  // they should never become invalid.
646  return finalizedItems.insert(GetVoteItemId(item)));
647  }
648 
649  if (!std::holds_alternative<const CBlockIndex *>(item)) {
650  continue;
651  }
652 
653  if (update.getStatus() == VoteStatus::Invalid) {
654  // Track invalidated blocks. Other invalidated types are not
655  // tracked because they may be rejected for transient reasons
656  // (ex: immature proofs or orphaned txs) With blocks this is not
657  // the case. A rejected block will not be mined on. To prevent
658  // reorgs, invalidated blocks should never be polled again.
660  invalidatedBlocks.insert(GetVoteItemId(item));
661  continue;
662  }
663 
664  // At this point the block index can only be finalized
665  const CBlockIndex *pindex = std::get<const CBlockIndex *>(item);
667  if (finalizationTip &&
668  finalizationTip->GetAncestor(pindex->nHeight) == pindex) {
669  continue;
670  }
671 
672  finalizationTip = pindex;
673  }
674 
675  return true;
676 }
677 
679  return sessionKey.GetPubKey();
680 }
681 
684 
685  Delegation delegation;
686  if (peerData) {
687  if (!canShareLocalProof()) {
688  if (!delayedAvahelloNodeIds.emplace(pfrom->GetId()).second) {
689  // Nothing to do
690  return false;
691  }
692  } else {
693  delegation = peerData->delegation;
694  }
695  }
696 
697  HashWriter hasher{};
698  hasher << delegation.getId();
699  hasher << pfrom->GetLocalNonce();
700  hasher << pfrom->nRemoteHostNonce;
701  hasher << pfrom->GetLocalExtraEntropy();
702  hasher << pfrom->nRemoteExtraEntropy;
703 
704  // Now let's sign!
705  SchnorrSig sig;
706  if (!sessionKey.SignSchnorr(hasher.GetHash(), sig)) {
707  return false;
708  }
709 
711  pfrom, CNetMsgMaker(pfrom->GetCommonVersion())
712  .Make(NetMsgType::AVAHELLO, Hello(delegation, sig)));
713 
714  return delegation.getLimitedProofId() != uint256::ZERO;
715 }
716 
719  return sendHelloInternal(pfrom));
720 }
721 
724 
725  auto it = delayedAvahelloNodeIds.begin();
726  while (it != delayedAvahelloNodeIds.end()) {
727  if (connman->ForNode(*it, [&](CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(
729  return sendHelloInternal(pnode);
730  })) {
731  // Our proof has been announced to this node
732  it = delayedAvahelloNodeIds.erase(it);
733  } else {
734  ++it;
735  }
736  }
737 }
738 
740  return peerData ? peerData->proof : ProofRef();
741 }
742 
744  return peerData
745  ? WITH_LOCK(peerData->cs_proofState, return peerData->proofState)
747 }
748 
750  return eventLoop.startEventLoop(
751  scheduler, [this]() { this->runEventLoop(); }, AVALANCHE_TIME_STEP);
752 }
753 
755  return eventLoop.stopEventLoop();
756 }
757 
760 
761  if (chainman.ActiveChainstate().IsInitialBlockDownload()) {
762  // Before IBD is complete there is no way to make sure a proof is valid
763  // or not, e.g. it can be spent in a block we don't know yet. In order
764  // to increase confidence that our proof set is similar to other nodes
765  // on the network, the messages received during IBD are not accounted.
766  return;
767  }
768 
770  if (peerManager->latchAvaproofsSent(nodeid)) {
772  }
773 }
774 
775 /*
776  * Returns a bool indicating whether we have a usable Avalanche quorum enabling
777  * us to take decisions based on polls.
778  */
781 
782  {
784  if (peerManager->getNodeCount() < 8) {
785  // There is no point polling if we know the vote cannot converge
786  return false;
787  }
788  }
789 
790  /*
791  * The following parameters can naturally go temporarly below the threshold
792  * under normal circumstances, like during a proof replacement with a lower
793  * stake amount, or the discovery of a new proofs for which we don't have a
794  * node yet.
795  * In order to prevent our node from starting and stopping the polls
796  * spuriously on such event, the quorum establishement is latched. The only
797  * parameters that should not latched is the minimum node count, as this
798  * would cause the poll to be inconclusive anyway and should not happen
799  * under normal circumstances.
800  */
801  if (quorumIsEstablished) {
802  return true;
803  }
804 
805  // Don't do Avalanche while node is IBD'ing
806  if (chainman.ActiveChainstate().IsInitialBlockDownload()) {
807  return false;
808  }
809 
811  return false;
812  }
813 
814  auto localProof = getLocalProof();
815 
816  // Get the registered proof score and registered score we have nodes for
817  uint32_t totalPeersScore;
818  uint32_t connectedPeersScore;
819  {
821  totalPeersScore = peerManager->getTotalPeersScore();
822  connectedPeersScore = peerManager->getConnectedPeersScore();
823 
824  // Consider that we are always connected to our proof, even if we are
825  // the single node using that proof.
826  if (localProof &&
827  peerManager->forPeer(localProof->getId(), [](const Peer &peer) {
828  return peer.node_count == 0;
829  })) {
830  connectedPeersScore += localProof->getScore();
831  }
832  }
833 
834  // Ensure enough is being staked overall
835  if (totalPeersScore < minQuorumScore) {
836  return false;
837  }
838 
839  // Ensure we have connected score for enough of the overall score
840  uint32_t minConnectedScore =
841  std::round(double(totalPeersScore) * minQuorumConnectedScoreRatio);
842  if (connectedPeersScore < minConnectedScore) {
843  return false;
844  }
845 
846  quorumIsEstablished = true;
847 
848  // Attempt to compute the staking rewards winner now so we don't have to
849  // wait for a block if we already have all the prerequisites.
850  const CBlockIndex *pprev = WITH_LOCK(cs_main, return chainman.ActiveTip());
851  if (pprev && IsStakingRewardsActivated(chainman.GetConsensus(), pprev)) {
852  computeStakingReward(pprev);
853  }
854 
855  return true;
856 }
857 
859  // The flag is latched
860  if (m_canShareLocalProof) {
861  return true;
862  }
863 
864  // Don't share our proof if we don't have any inbound connection.
865  // This is a best effort measure to prevent advertising a proof if we have
866  // limited network connectivity.
868 
869  return m_canShareLocalProof;
870 }
871 
873  if (!pindex) {
874  return false;
875  }
876 
877  // If the quorum is not established there is no point picking a winner that
878  // will be rejected.
879  if (!isQuorumEstablished()) {
880  return false;
881  }
882 
883  {
885  if (stakingRewards.count(pindex->GetBlockHash()) > 0) {
886  return true;
887  }
888  }
889 
890  StakingReward _stakingRewards;
891  _stakingRewards.blockheight = pindex->nHeight;
892 
893  if (WITH_LOCK(cs_peerManager, return peerManager->selectStakingRewardWinner(
894  pindex, _stakingRewards.winners))) {
896  return stakingRewards
897  .emplace(pindex->GetBlockHash(), std::move(_stakingRewards))
898  .second;
899  }
900 
901  return false;
902 }
903 
904 bool Processor::eraseStakingRewardWinner(const BlockHash &prevBlockHash) {
906  return stakingRewards.erase(prevBlockHash) > 0;
907 }
908 
909 void Processor::cleanupStakingRewards(const int minHeight) {
911  // std::erase_if is only defined since C++20
912  for (auto it = stakingRewards.begin(); it != stakingRewards.end();) {
913  if (it->second.blockheight < minHeight) {
914  it = stakingRewards.erase(it);
915  } else {
916  ++it;
917  }
918  }
919 }
920 
922  const BlockHash &prevBlockHash,
923  std::vector<std::pair<ProofId, CScript>> &winners) const {
925  auto it = stakingRewards.find(prevBlockHash);
926  if (it == stakingRewards.end()) {
927  return false;
928  }
929 
930  winners = it->second.winners;
931  return true;
932 }
933 
935  std::vector<CScript> &payouts) const {
936  std::vector<std::pair<ProofId, CScript>> winners;
937  if (!getStakingRewardWinners(prevBlockHash, winners)) {
938  return false;
939  }
940 
941  payouts.clear();
942  payouts.reserve(winners.size());
943  for (auto &winner : winners) {
944  payouts.push_back(std::move(winner.second));
945  }
946 
947  return true;
948 }
949 
951  const std::vector<CScript> &payouts) {
952  assert(pprev);
953 
954  StakingReward stakingReward;
955  stakingReward.blockheight = pprev->nHeight;
956 
957  stakingReward.winners.reserve(payouts.size());
958  for (const CScript &payout : payouts) {
959  stakingReward.winners.push_back({ProofId(), payout});
960  }
961 
963  return stakingRewards.insert_or_assign(pprev->GetBlockHash(), stakingReward)
964  .second;
965 }
966 
967 void Processor::FinalizeNode(const ::Config &config, const CNode &node) {
969 
970  const NodeId nodeid = node.GetId();
971  WITH_LOCK(cs_peerManager, peerManager->removeNode(nodeid));
972  WITH_LOCK(cs_delayedAvahelloNodeIds, delayedAvahelloNodeIds.erase(nodeid));
973 }
974 
976  const bool registerLocalProof = canShareLocalProof();
977  auto registerProofs = [&]() {
979 
980  auto registeredProofs = peerManager->updatedBlockTip();
981 
982  ProofRegistrationState localProofState;
983  if (peerData && peerData->proof && registerLocalProof) {
984  if (peerManager->registerProof(peerData->proof, localProofState)) {
985  registeredProofs.insert(peerData->proof);
986  }
987 
988  if (localProofState.GetResult() ==
990  // If our proof already exists, that's fine but we don't want to
991  // erase the state with a duplicated proof status, so let's
992  // retrieve the proper state. It also means we are able to
993  // update the status should the proof move from one pool to the
994  // other.
995  const ProofId &localProofId = peerData->proof->getId();
996  if (peerManager->isImmature(localProofId)) {
998  "immature-proof");
999  }
1000  if (peerManager->isInConflictingPool(localProofId)) {
1001  localProofState.Invalid(
1003  "conflicting-utxos");
1004  }
1005  if (peerManager->isBoundToPeer(localProofId)) {
1006  localProofState = ProofRegistrationState();
1007  }
1008  }
1009 
1010  WITH_LOCK(peerData->cs_proofState,
1011  peerData->proofState = std::move(localProofState));
1012  }
1013 
1014  return registeredProofs;
1015  };
1016 
1017  auto registeredProofs = registerProofs();
1018  for (const auto &proof : registeredProofs) {
1019  reconcileOrFinalize(proof);
1020  }
1021 }
1022 
1024  if (m_preConsensus) {
1025  addToReconcile(tx);
1026  }
1027 }
1028 
1030  // Don't poll if quorum hasn't been established yet
1031  if (!isQuorumEstablished()) {
1032  return;
1033  }
1034 
1035  // First things first, check if we have requests that timed out and clear
1036  // them.
1038 
1039  // Make sure there is at least one suitable node to query before gathering
1040  // invs.
1041  NodeId nodeid = WITH_LOCK(cs_peerManager, return peerManager->selectNode());
1042  if (nodeid == NO_NODE) {
1043  return;
1044  }
1045  std::vector<CInv> invs = getInvsForNextPoll();
1046  if (invs.empty()) {
1047  return;
1048  }
1049 
1051 
1052  do {
1058  bool hasSent = connman->ForNode(
1059  nodeid, [this, &invs](CNode *pnode) EXCLUSIVE_LOCKS_REQUIRED(
1060  cs_peerManager) {
1061  uint64_t current_round = round++;
1062 
1063  {
1064  // Compute the time at which this requests times out.
1065  auto timeout = Now<SteadyMilliseconds>() +
1067  // Register the query.
1068  queries.getWriteView()->insert(
1069  {pnode->GetId(), current_round, timeout, invs});
1070  // Set the timeout.
1071  peerManager->updateNextRequestTime(pnode->GetId(), timeout);
1072  }
1073 
1074  pnode->invsPolled(invs.size());
1075 
1076  // Send the query to the node.
1078  pnode, CNetMsgMaker(pnode->GetCommonVersion())
1080  Poll(current_round, std::move(invs))));
1081  return true;
1082  });
1083 
1084  // Success!
1085  if (hasSent) {
1086  return;
1087  }
1088 
1089  // This node is obsolete, delete it.
1090  peerManager->removeNode(nodeid);
1091 
1092  // Get next suitable node to try again
1093  nodeid = peerManager->selectNode();
1094  } while (nodeid != NO_NODE);
1095 }
1096 
1098  auto now = Now<SteadyMilliseconds>();
1099  std::map<CInv, uint8_t> timedout_items{};
1100 
1101  {
1102  // Clear expired requests.
1103  auto w = queries.getWriteView();
1104  auto it = w->get<query_timeout>().begin();
1105  while (it != w->get<query_timeout>().end() && it->timeout < now) {
1106  for (const auto &i : it->invs) {
1107  timedout_items[i]++;
1108  }
1109 
1110  w->get<query_timeout>().erase(it++);
1111  }
1112  }
1113 
1114  if (timedout_items.empty()) {
1115  return;
1116  }
1117 
1118  // In flight request accounting.
1119  auto voteRecordsWriteView = voteRecords.getWriteView();
1120  for (const auto &p : timedout_items) {
1121  auto item = getVoteItemFromInv(p.first);
1122 
1123  if (isNull(item)) {
1124  continue;
1125  }
1126 
1127  auto it = voteRecordsWriteView->find(item);
1128  if (it == voteRecordsWriteView.end()) {
1129  continue;
1130  }
1131 
1132  it->second.clearInflightRequest(p.second);
1133  }
1134 }
1135 
1136 std::vector<CInv> Processor::getInvsForNextPoll(bool forPoll) {
1137  std::vector<CInv> invs;
1138 
1139  {
1140  // First remove all items that are not worth polling.
1141  auto w = voteRecords.getWriteView();
1142  for (auto it = w->begin(); it != w->end();) {
1143  if (!isWorthPolling(it->first)) {
1144  it = w->erase(it);
1145  } else {
1146  ++it;
1147  }
1148  }
1149  }
1150 
1151  auto buildInvFromVoteItem = variant::overloaded{
1152  [](const ProofRef &proof) {
1153  return CInv(MSG_AVA_PROOF, proof->getId());
1154  },
1155  [](const CBlockIndex *pindex) {
1156  return CInv(MSG_BLOCK, pindex->GetBlockHash());
1157  },
1158  [](const CTransactionRef &tx) { return CInv(MSG_TX, tx->GetHash()); },
1159  };
1160 
1161  auto r = voteRecords.getReadView();
1162  for (const auto &[item, voteRecord] : r) {
1163  if (invs.size() >= AVALANCHE_MAX_ELEMENT_POLL) {
1164  // Make sure we do not produce more invs than specified by the
1165  // protocol.
1166  return invs;
1167  }
1168 
1169  const bool shouldPoll =
1170  forPoll ? voteRecord.registerPoll() : voteRecord.shouldPoll();
1171 
1172  if (!shouldPoll) {
1173  continue;
1174  }
1175 
1176  invs.emplace_back(std::visit(buildInvFromVoteItem, item));
1177  }
1178 
1179  return invs;
1180 }
1181 
1183  if (inv.IsMsgBlk()) {
1185  BlockHash(inv.hash)));
1186  }
1187 
1188  if (inv.IsMsgProof()) {
1189  return WITH_LOCK(cs_peerManager,
1190  return peerManager->getProof(ProofId(inv.hash)));
1191  }
1192 
1193  if (mempool && inv.IsMsgTx()) {
1194  return WITH_LOCK(mempool->cs, return mempool->get(TxId(inv.hash)));
1195  }
1196 
1197  return {nullptr};
1198 }
1199 
1202 
1203  LOCK(cs_main);
1204 
1205  if (pindex->nStatus.isInvalid()) {
1206  // No point polling invalid blocks.
1207  return false;
1208  }
1209 
1211  return processor.finalizationTip &&
1212  processor.finalizationTip->GetAncestor(
1213  pindex->nHeight) == pindex)) {
1214  // There is no point polling blocks that are ancestor of a block that
1215  // has been accepted by the network.
1216  return false;
1217  }
1218 
1220  return processor.invalidatedBlocks.contains(
1221  pindex->GetBlockHash()))) {
1222  // Blocks invalidated by Avalanche should not be polled twice.
1223  return false;
1224  }
1225 
1226  return true;
1227 }
1228 
1230  // Avoid lock order issues cs_main -> cs_peerManager
1232  AssertLockNotHeld(processor.cs_peerManager);
1233 
1234  const ProofId &proofid = proof->getId();
1235 
1236  LOCK(processor.cs_peerManager);
1237 
1238  // No point polling immature or discarded proofs
1239  return processor.peerManager->isBoundToPeer(proofid) ||
1240  processor.peerManager->isInConflictingPool(proofid);
1241 }
1242 
1244  if (!processor.mempool) {
1245  return false;
1246  }
1247 
1248  // TODO For now the transactions with conflicts or rejected by policies are
1249  // not stored anywhere, so only the mempool transactions are worth polling.
1250  AssertLockNotHeld(processor.mempool->cs);
1251  return WITH_LOCK(processor.mempool->cs,
1252  return processor.mempool->exists(tx->GetId()));
1253 }
1254 
1255 bool Processor::isWorthPolling(const AnyVoteItem &item) const {
1256  return std::visit(IsWorthPolling(*this), item) &&
1258 }
1259 
1261  const CBlockIndex *pindex) const {
1263 
1264  return WITH_LOCK(cs_main,
1265  return processor.chainman.ActiveChain().Contains(pindex));
1266 }
1267 
1269  AssertLockNotHeld(processor.cs_peerManager);
1270 
1271  return WITH_LOCK(
1272  processor.cs_peerManager,
1273  return processor.peerManager->isBoundToPeer(proof->getId()));
1274 }
1275 
1277  const CTransactionRef &tx) const {
1278  if (!processor.mempool) {
1279  return false;
1280  }
1281 
1282  AssertLockNotHeld(processor.mempool->cs);
1283 
1284  return WITH_LOCK(processor.mempool->cs,
1285  return processor.mempool->exists(tx->GetId()));
1286 }
1287 
1288 } // namespace avalanche
bool MoneyRange(const Amount nValue)
Definition: amount.h:166
ArgsManager gArgs
Definition: args.cpp:38
uint32_t PeerId
Definition: node.h:15
static constexpr bool DEFAULT_PERSIST_AVAPEERS
Default for -persistavapeers.
Definition: avalanche.h:63
static constexpr double AVALANCHE_DEFAULT_MIN_QUORUM_CONNECTED_STAKE_RATIO
Default minimum percentage of stake-weighted peers we must have a node for to constitute a usable quo...
Definition: avalanche.h:53
static constexpr double AVALANCHE_DEFAULT_MIN_AVAPROOFS_NODE_COUNT
Default minimum number of nodes that sent us an avaproofs message before we can consider our quorum s...
Definition: avalanche.h:60
static constexpr bool DEFAULT_AVALANCHE_PRECONSENSUS
Default for -avalanchepreconsensus.
Definition: avalanche.h:66
static constexpr Amount AVALANCHE_DEFAULT_MIN_QUORUM_STAKE
Default minimum cumulative stake of all known peers that constitutes a usable quorum.
Definition: avalanche.h:46
bool IsArgSet(const std::string &strArg) const
Return true if the given argument has been manually set.
Definition: args.cpp:381
const fs::path & GetDataDirNet() const
Get data directory path with appended network identifier.
Definition: args.h:215
int64_t GetIntArg(const std::string &strArg, int64_t nDefault) const
Return integer argument or default value.
Definition: args.cpp:526
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: args.cpp:494
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:556
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: blockindex.h:25
BlockHash GetBlockHash() const
Definition: blockindex.h:146
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: blockindex.h:38
Definition: net.h:845
size_t GetNodeCount(NumConnections num) const
Definition: net.cpp:3249
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
Definition: net.cpp:3539
@ CONNECTIONS_IN
Definition: net.h:849
void PushMessage(CNode *pnode, CSerializedNetMsg &&msg)
Definition: net.cpp:3494
Inv(ventory) message data.
Definition: protocol.h:580
bool IsMsgBlk() const
Definition: protocol.h:607
bool IsMsgTx() const
Definition: protocol.h:599
uint256 hash
Definition: protocol.h:583
bool IsMsgProof() const
Definition: protocol.h:603
An encapsulated secp256k1 private key.
Definition: key.h:28
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:94
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
Definition: key.cpp:183
CPubKey GetPubKey() const
Compute the public key from a private key.
Definition: key.cpp:210
bool SignSchnorr(const uint256 &hash, SchnorrSig &sig, uint32_t test_case=0) const
Create a Schnorr signature.
Definition: key.cpp:288
CSerializedNetMsg Make(int nFlags, std::string msg_type, Args &&...args) const
Information about a peer.
Definition: net.h:456
NodeId GetId() const
Definition: net.h:712
uint64_t GetLocalNonce() const
Definition: net.h:714
int GetCommonVersion() const
Definition: net.h:738
uint64_t nRemoteHostNonce
Definition: net.h:497
uint64_t nRemoteExtraEntropy
Definition: net.h:499
uint64_t GetLocalExtraEntropy() const
Definition: net.h:715
void invsPolled(uint32_t count)
The node was polled for count invs.
Definition: net.cpp:3418
An encapsulated public key.
Definition: pubkey.h:31
Simple class for background tasks that should be run periodically or once "after a while".
Definition: scheduler.h:41
void scheduleEvery(Predicate p, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat p until it return false.
Definition: scheduler.cpp:114
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:431
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
Definition: txmempool.h:209
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
Definition: txmempool.h:296
CTransactionRef get(const TxId &txid) const
Definition: txmempool.cpp:505
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1218
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Definition: validation.h:1434
const Consensus::Params & GetConsensus() const
Definition: validation.h:1315
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
Definition: validation.h:1350
A writer stream (for serialization) that computes a 256-bit hash.
Definition: hash.h:99
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
Definition: rcu.h:112
ReadView getReadView() const
Definition: rwcollection.h:78
WriteView getWriteView()
Definition: rwcollection.h:84
bool Invalid(Result result, const std::string &reject_reason="", const std::string &debug_message="")
Definition: validation.h:99
Result GetResult() const
Definition: validation.h:120
ProofId getProofId() const
Definition: delegation.cpp:56
static bool FromHex(Delegation &dg, const std::string &dgHex, bilingual_str &errorOut)
Definition: delegation.cpp:16
bool verify(DelegationState &state, CPubKey &auth) const
Definition: delegation.cpp:73
const LimitedProofId & getLimitedProofId() const
Definition: delegation.h:61
const CPubKey & getDelegatedPubkey() const
Definition: delegation.cpp:60
const DelegationId & getId() const
Definition: delegation.h:60
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
Definition: processor.cpp:135
void sendResponse(CNode *pfrom, Response response) const
Definition: processor.cpp:510
const uint32_t staleVoteThreshold
Voting parameters.
Definition: processor.h:253
std::atomic< bool > quorumIsEstablished
Definition: processor.h:247
AnyVoteItem getVoteItemFromInv(const CInv &inv) const EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:1182
Mutex cs_finalizedItems
Rolling bloom filter to track recently finalized inventory items of any type.
Definition: processor.h:421
bool sendHelloInternal(CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(cs_delayedAvahelloNodeIds)
Definition: processor.cpp:682
int getConfidence(const AnyVoteItem &item) const
Definition: processor.cpp:458
bool addToReconcile(const AnyVoteItem &item) EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:407
std::vector< CInv > getInvsForNextPoll(bool forPoll=true) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:1136
RWCollection< QuerySet > queries
Definition: processor.h:232
bool registerVotes(NodeId nodeid, const Response &response, std::vector< VoteItemUpdate > &updates, int &banscore, std::string &error) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:517
void transactionAddedToMempool(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:1023
bool sendHello(CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
Send a avahello message.
Definition: processor.cpp:717
bool isRecentlyFinalized(const uint256 &itemId) const EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:472
bool startEventLoop(CScheduler &scheduler)
Definition: processor.cpp:749
bool isQuorumEstablished() LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:779
bool getStakingRewardWinners(const BlockHash &prevBlockHash, std::vector< std::pair< ProofId, CScript >> &winners) const EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards)
Definition: processor.cpp:921
std::atomic< uint64_t > round
Keep track of peers and queries sent.
Definition: processor.h:196
static std::unique_ptr< Processor > MakeProcessor(const ArgsManager &argsman, interfaces::Chain &chain, CConnman *connman, ChainstateManager &chainman, CTxMemPool *mempoolIn, CScheduler &scheduler, bilingual_str &error)
Definition: processor.cpp:217
EventLoop eventLoop
Event loop machinery.
Definition: processor.h:240
CTxMemPool * mempool
Definition: processor.h:186
int64_t minAvaproofsNodeCount
Definition: processor.h:249
const bool m_preConsensus
Definition: processor.h:281
Mutex cs_delayedAvahelloNodeIds
Definition: processor.h:261
void runEventLoop() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:1029
Mutex cs_invalidatedBlocks
We don't need many blocks but a low false positive rate.
Definition: processor.h:419
void updatedBlockTip() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:975
RWCollection< VoteMap > voteRecords
Items to run avalanche on.
Definition: processor.h:191
std::unique_ptr< interfaces::Handler > chainNotificationsHandler
Definition: processor.h:257
uint32_t minQuorumScore
Quorum management.
Definition: processor.h:245
void FinalizeNode(const ::Config &config, const CNode &node) override LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Handle removal of a node.
Definition: processor.cpp:967
std::atomic< bool > m_canShareLocalProof
Definition: processor.h:248
bool isAccepted(const AnyVoteItem &item) const
Definition: processor.cpp:444
ProofRef getLocalProof() const
Definition: processor.cpp:739
bool reconcileOrFinalize(const ProofRef &proof) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Wrapper around the addToReconcile for proofs that adds back the finalization flag to the peer if it i...
Definition: processor.cpp:425
const uint32_t staleVoteFactor
Definition: processor.h:254
void sendDelayedAvahello() EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
Definition: processor.cpp:722
std::unique_ptr< PeerData > peerData
Definition: processor.h:235
bool eraseStakingRewardWinner(const BlockHash &prevBlockHash) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards)
Definition: processor.cpp:904
CConnman * connman
Definition: processor.h:184
bool isWorthPolling(const AnyVoteItem &item) const EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:1255
CPubKey getSessionPubKey() const
Definition: processor.cpp:678
Processor(Config avaconfig, interfaces::Chain &chain, CConnman *connmanIn, ChainstateManager &chainman, CTxMemPool *mempoolIn, CScheduler &scheduler, std::unique_ptr< PeerData > peerDataIn, CKey sessionKeyIn, uint32_t minQuorumTotalScoreIn, double minQuorumConnectedScoreRatioIn, int64_t minAvaproofsNodeCountIn, uint32_t staleVoteThresholdIn, uint32_t staleVoteFactorIn, Amount stakeUtxoDustThresholdIn, bool preConsensus)
Definition: processor.cpp:141
ChainstateManager & chainman
Definition: processor.h:185
std::atomic< int64_t > avaproofsNodeCounter
Definition: processor.h:250
bool computeStakingReward(const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Definition: processor.cpp:872
ProofRegistrationState getLocalProofRegistrationState() const
Definition: processor.cpp:743
bool setStakingRewardWinners(const CBlockIndex *pprev, const std::vector< CScript > &payouts) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards)
Definition: processor.cpp:950
void cleanupStakingRewards(const int minHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards)
Definition: processor.cpp:909
void clearTimedoutRequests() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:1097
Mutex cs_peerManager
Keep track of the peers and associated infos.
Definition: processor.h:201
bool getLocalAcceptance(const AnyVoteItem &item) const
Definition: processor.h:462
void avaproofsSent(NodeId nodeid) LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Definition: processor.cpp:758
double minQuorumConnectedScoreRatio
Definition: processor.h:246
void clearFinalizedItems() EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
Definition: processor.cpp:476
static bool FromHex(Proof &proof, const std::string &hexProof, bilingual_str &errorOut)
Definition: proof.cpp:51
bool verify(const Amount &stakeUtxoDustThreshold, ProofValidationState &state) const
Definition: proof.cpp:119
static uint32_t amountToScore(Amount amount)
Definition: proof.cpp:100
uint32_t GetError() const
Definition: protocol.h:27
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:30
Chain notifications.
Definition: chain.h:241
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
Definition: chain.h:123
virtual std::unique_ptr< Handler > handleNotifications(std::shared_ptr< Notifications > notifications)=0
Register handler for notifications.
CBlockIndex * LookupBlockIndex(const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
256-bit opaque blob.
Definition: uint256.h:129
static const uint256 ZERO
Definition: uint256.h:134
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
std::array< uint8_t, CPubKey::SCHNORR_SIZE > SchnorrSig
a Schnorr signature
Definition: key.h:25
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:77
bool error(const char *fmt, const Args &...args)
Definition: logging.h:226
#define LogPrint(category,...)
Definition: logging.h:211
bool ParseMoney(const std::string &money_string, Amount &nRet)
Parse an amount denoted in full coins.
Definition: moneystr.cpp:37
@ AVALANCHE
Definition: logging.h:62
const char * AVAHELLO
Contains a delegation and a signature.
Definition: protocol.cpp:51
const char * AVARESPONSE
Contains an avalanche::Response.
Definition: protocol.cpp:53
const char * AVAPOLL
Contains an avalanche::Poll.
Definition: protocol.cpp:52
static constexpr Amount PROOF_DUST_THRESHOLD
Minimum amount per utxo.
Definition: proof.h:40
std::map< AnyVoteItem, VoteRecord, VoteMapComparator > VoteMap
Definition: processor.h:172
static bool VerifyDelegation(const Delegation &dg, const CPubKey &expectedPubKey, bilingual_str &error)
Definition: processor.cpp:88
static bool isNull(const AnyVoteItem &item)
Definition: processor.cpp:402
std::variant< const ProofRef, const CBlockIndex *, const CTransactionRef > AnyVoteItem
Definition: processor.h:87
static const uint256 GetVoteItemId(const AnyVoteItem &item)
Definition: processor.cpp:38
static bool VerifyProof(const Amount &stakeUtxoDustThreshold, const Proof &proof, bilingual_str &error)
Definition: processor.cpp:56
RCUPtr< const Proof > ProofRef
Definition: proof.h:185
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:142
Definition: init.h:28
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:257
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
Definition: nodeid.h:15
int64_t NodeId
Definition: nodeid.h:10
std::shared_ptr< const CTransaction > CTransactionRef
Definition: transaction.h:315
static const std::string AVAPEERS_FILE_NAME
Definition: processor.cpp:35
Response response
Definition: processor.cpp:487
static constexpr std::chrono::milliseconds AVALANCHE_TIME_STEP
Run the avalanche event loop every 10ms.
Definition: processor.cpp:33
SchnorrSig sig
Definition: processor.cpp:488
static constexpr std::chrono::milliseconds AVALANCHE_DEFAULT_QUERY_TIMEOUT
How long before we consider that a query timed out.
Definition: processor.h:57
static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
Definition: processor.h:52
static constexpr int AVALANCHE_MAX_PROOF_STAKES
How many UTXOs can be used for a single proof.
Definition: proof.h:29
@ MSG_TX
Definition: protocol.h:565
@ MSG_AVA_PROOF
Definition: protocol.h:572
@ MSG_BLOCK
Definition: protocol.h:566
#define SERIALIZE_METHODS(cls, obj)
Implement the Serialize and Unserialize methods by delegating to a single templated static method tha...
Definition: serialize.h:213
#define READWRITE(...)
Definition: serialize.h:166
bool IsStakingRewardsActivated(const Consensus::Params &params, const CBlockIndex *pprev)
bool ParseDouble(const std::string &str, double *out)
Convert string to double with strict parse error feedback.
Definition: amount.h:19
A BlockHash is a unqiue identifier for a block.
Definition: blockhash.h:13
bool stopEventLoop() EXCLUSIVE_LOCKS_REQUIRED(!cs_running)
Definition: eventloop.cpp:45
bool startEventLoop(CScheduler &scheduler, std::function< void()> runEventLoop, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!cs_running)
Definition: eventloop.cpp:13
A TxId is the identifier of a transaction.
Definition: txid.h:14
const std::chrono::milliseconds queryTimeoutDuration
Definition: config.h:13
bool operator()(const CBlockIndex *pindex) const LOCKS_EXCLUDED(cs_main)
Definition: processor.cpp:1260
bool operator()(const CBlockIndex *pindex) const LOCKS_EXCLUDED(cs_main)
Definition: processor.cpp:1200
ProofRegistrationState proofState GUARDED_BY(cs_proofState)
std::vector< std::pair< ProofId, CScript > > winners
Definition: processor.h:274
Vote history.
Definition: voterecord.h:49
Bilingual messages:
Definition: translation.h:17
#define AssertLockNotHeld(cs)
Definition: sync.h:163
#define LOCK(cs)
Definition: sync.h:306
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
Definition: sync.h:357
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:56
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
bilingual_str _(const char *psz)
Translation function.
Definition: translation.h:68
AssertLockHeld(pool.cs)
assert(!tx.IsCoinBase())
static constexpr uint32_t AVALANCHE_VOTE_STALE_FACTOR
Scaling factor applied to confidence to determine staleness threshold.
Definition: voterecord.h:35
static constexpr uint32_t AVALANCHE_VOTE_STALE_MIN_THRESHOLD
Lowest configurable staleness threshold (finalization score + necessary votes to increase confidence ...
Definition: voterecord.h:28
static constexpr uint32_t AVALANCHE_VOTE_STALE_THRESHOLD
Number of votes before a record may be considered as stale.
Definition: voterecord.h:22