46 uint256 hash = pindex->GetBlockHash();
64 error =
_(
"The avalanche proof has no stake.");
67 error =
_(
"The avalanche proof stake is too low.");
70 error =
_(
"The avalanche proof has duplicated stake.");
73 error =
_(
"The avalanche proof has invalid stake signatures.");
77 _(
"The avalanche proof has too many utxos (max: %u)."),
81 error =
_(
"The avalanche proof is invalid.");
98 error =
_(
"The avalanche delegation has invalid signatures.");
102 "The avalanche delegation has too many delegation levels.");
105 error =
_(
"The avalanche delegation is invalid.");
112 "The avalanche delegation does not match the expected public key.");
155 stakeUtxoDustThreshold, chainman,
175 "Promoting previously dangling proof %s\n",
176 proof->getId().ToString());
218std::unique_ptr<Processor>
228 if (
argsman.IsArgSet(
"-avaproofstakeutxodustthreshold") &&
230 stakeUtxoDustThreshold)) {
231 error =
_(
"The avalanche stake utxo dust threshold amount is invalid.");
235 if (
argsman.IsArgSet(
"-avasessionkey")) {
238 error =
_(
"The avalanche session key is invalid.");
246 if (
argsman.IsArgSet(
"-avaproof")) {
247 if (!
argsman.IsArgSet(
"-avamasterkey")) {
249 "The avalanche master key is missing for the avalanche proof.");
255 error =
_(
"The avalanche master key is invalid.");
265 peerData = std::make_unique<PeerData>();
272 std::unique_ptr<DelegationBuilder>
dgb;
275 if (
argsman.IsArgSet(
"-avadelegation")) {
283 if (
dg.getProofId() !=
peerData->proof->getId()) {
284 error =
_(
"The delegation does not match the proof.");
290 "The master key does not match the delegation public key.");
294 dgb = std::make_unique<DelegationBuilder>(
dg);
298 _(
"The master key does not match the proof public key.");
302 dgb = std::make_unique<DelegationBuilder>(*
peerData->proof);
309 error =
_(
"Failed to generate a delegation for this session.");
321 const auto queryTimeoutDuration =
322 std::chrono::milliseconds(
argsman.GetIntArg(
327 if (
argsman.IsArgSet(
"-avaminquorumstake") &&
329 error =
_(
"The avalanche min quorum stake amount is invalid.");
334 error =
_(
"The avalanche min quorum stake amount is out of range.");
340 if (
argsman.IsArgSet(
"-avaminquorumconnectedstakeratio")) {
344 argsman.GetArg(
"-avaminquorumconnectedstakeratio",
""), 6,
347 _(
"The avalanche min quorum connected stake ratio is invalid.");
355 "The avalanche min quorum connected stake ratio is out of range.");
360 argsman.GetIntArg(
"-avaminavaproofsnodecount",
363 error =
_(
"The minimum number of node that sent avaproofs message "
364 "should be non-negative");
373 "greater than or equal to %d"),
379 "than or equal to %d"),
380 std::numeric_limits<uint32_t>::max());
387 error =
_(
"The avalanche stale vote factor must be greater than 0");
391 error =
strprintf(
_(
"The avalanche stale vote factor must be less than "
393 std::numeric_limits<uint32_t>::max());
400 return std::unique_ptr<Processor>(
new Processor(
405 stakeUtxoDustThreshold,
406 argsman.GetBoolArg(
"-avalanchepreconsensus",
408 argsman.GetBoolArg(
"-avalanchestakingpreconsensus",
413 return item.valueless_by_exception() ||
414 std::visit([](
const auto &item) {
return item ==
nullptr; }, item);
444 peerid = peer.peerid;
460 auto it = r->find(item);
465 return it->second.isAccepted();
474 auto it = r->find(item);
479 return it->second.getConfidence();
505 const uint256 hash = hasher.GetHash();
528 std::vector<VoteItemUpdate> &updates,
539 std::chrono::milliseconds(
response.getCooldown()));
542 std::vector<CInv> invs;
550 auto it = w->find(std::make_tuple(nodeid,
response.getRound()));
553 error =
"unexpected-ava-response";
557 invs = std::move(it->invs);
562 const std::vector<Vote> &votes =
response.GetVotes();
563 size_t size = invs.size();
564 if (votes.size() != size) {
566 error =
"invalid-ava-response-size";
570 for (
size_t i = 0; i < size; i++) {
571 if (invs[i].hash != votes[i].GetHash()) {
573 error =
"invalid-ava-response-content";
578 std::map<AnyVoteItem, Vote, VoteMapComparator>
responseItems;
582 for (
size_t i = 0; i < size; i++) {
595 responseItems.insert(std::make_pair(std::move(item), votes[i]));
603 const Vote &v =
p.second;
611 auto &
vr = it->second;
624 if (!
vr.hasFinalized()) {
627 updates.emplace_back(std::move(item),
vr.isAccepted()
635 updates.emplace_back(std::move(item),
vr.isAccepted()
643 for (
const auto &
update : updates) {
649 const auto &item =
update.getVoteItem();
658 if (!std::holds_alternative<const CBlockIndex *>(item)) {
674 const CBlockIndex *pindex = std::get<const CBlockIndex *>(item);
707 hasher << delegation.
getId();
708 hasher <<
pfrom->GetLocalNonce();
709 hasher <<
pfrom->nRemoteHostNonce;
710 hasher <<
pfrom->GetLocalExtraEntropy();
711 hasher <<
pfrom->nRemoteExtraEntropy;
830 totalPeersScore =
peerManager->getTotalPeersScore();
831 connectedPeersScore =
peerManager->getConnectedPeersScore();
837 return peer.node_count == 0;
839 connectedPeersScore += localProof->getScore();
931 if (it->second.blockheight <
minHeight) {
947 std::vector<std::pair<ProofId, CScript>> &winners)
const {
954 winners = it->second.winners;
959 std::vector<CScript> &
payouts)
const {
960 std::vector<std::pair<ProofId, CScript>> winners;
966 payouts.reserve(winners.size());
967 for (
auto &
winner : winners) {
975 const std::vector<CScript> &
payouts) {
1018 std::vector<std::pair<ProofId, CScript>> winners;
1021 if (status != -1 && winners.size() == 0) {
1055 std::vector<std::pair<ProofId, CScript>> winners;
1057 if (winners.size() == 0) {
1095 "conflicting-utxos");
1170 pnode->invsPolled(invs.size());
1201 while (it != w->get<
query_timeout>().end() && it->timeout < now) {
1202 for (
const auto &i : it->invs) {
1228 it->second.clearInflightRequest(
p.second);
1233 std::vector<CInv> invs;
1238 for (
auto it = w->begin(); it != w->end();) {
1265 const bool shouldPoll =
1279 if (
inv.IsMsgBlk()) {
1284 if (
inv.IsMsgProof()) {
1296 return conflicting.GetTx(TxId(inv.hash));
1310 if (pindex->nStatus.isInvalid()) {
1318 pindex->
nHeight) == pindex)) {
1325 return processor.invalidatedBlocks.contains(
1339 const ProofId &proofid = proof->getId();
1341 LOCK(processor.cs_peerManager);
1344 return processor.peerManager->isBoundToPeer(proofid) ||
1345 processor.peerManager->isInConflictingPool(proofid);
1349 if (!processor.mempool) {
1354 LOCK(processor.mempool->cs);
1356 return processor.mempool->exists(tx->GetId()) ||
1357 processor.mempool->withConflicting(
1373 return processor.chainman.ActiveChain().Contains(pindex));
1380 processor.cs_peerManager,
1381 return processor.peerManager->isBoundToPeer(proof->getId()));
1386 if (!processor.mempool) {
1393 return processor.mempool->exists(tx->GetId()));
bool MoneyRange(const Amount nValue)
static constexpr bool DEFAULT_PERSIST_AVAPEERS
Default for -persistavapeers.
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...
static constexpr bool DEFAULT_AVALANCHE_STAKING_PRECONSENSUS
Default for -avalanchestakingpreconsensus.
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...
static constexpr bool DEFAULT_AVALANCHE_PRECONSENSUS
Default for -avalanchepreconsensus.
static constexpr Amount AVALANCHE_DEFAULT_MIN_QUORUM_STAKE
Default minimum cumulative stake of all known peers that constitutes a usable quorum.
fs::path GetDataDirNet() const
Get data directory path with appended network identifier.
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
The block chain is a tree shaped structure starting with the genesis block at the root,...
BlockHash GetBlockHash() const
int nHeight
height of the entry in the chain. The genesis block has height 0
bool ForNode(NodeId id, std::function< bool(CNode *pnode)> func)
size_t GetNodeCount(ConnectionDirection) const
void PushMessage(CNode *pnode, CSerializedNetMsg &&msg)
Inv(ventory) message data.
An encapsulated secp256k1 private key.
bool IsValid() const
Check whether this private key is valid.
void MakeNewKey(bool fCompressed)
Generate a new private key using a cryptographic PRNG.
CPubKey GetPubKey() const
Compute the public key from a private key.
bool SignSchnorr(const uint256 &hash, SchnorrSig &sig, uint32_t test_case=0) const
Create a Schnorr signature.
CSerializedNetMsg Make(int nFlags, std::string msg_type, Args &&...args) const
Information about a peer.
An encapsulated public key.
Simple class for background tasks that should be run periodically or once "after a while".
void scheduleEvery(Predicate p, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
Repeat p until it return false.
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.
CTransactionRef get(const TxId &txid) const
auto withConflicting(Callable &&func) const EXCLUSIVE_LOCKS_REQUIRED(!cs_conflicting)
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
SnapshotCompletionResult MaybeCompleteSnapshotValidation(std::function< void(bilingual_str)> shutdown_fnc=[](bilingual_str msg) { AbortNode(msg.original, msg);}) EXCLUSIVE_LOCKS_REQUIRED(Chainstate & ActiveChainstate() const
Once the background validation chainstate has reached the height which is the base of the UTXO snapsh...
const Consensus::Params & GetConsensus() const
node::BlockManager m_blockman
A single BlockManager instance is shared across each constructed chainstate to avoid duplicating bloc...
A writer stream (for serialization) that computes a 256-bit hash.
static RCUPtr make(Args &&...args)
Construct a new object that is owned by the pointer.
ReadView getReadView() const
static bool FromHex(Delegation &dg, const std::string &dgHex, bilingual_str &errorOut)
const DelegationId & getId() const
const LimitedProofId & getLimitedProofId() const
void updatedBlockTip() override
NotificationsHandler(Processor *p)
void transactionAddedToMempool(const CTransactionRef &tx, uint64_t mempool_sequence) override
void sendResponse(CNode *pfrom, Response response) const
const uint32_t staleVoteThreshold
Voting parameters.
std::atomic< bool > quorumIsEstablished
AnyVoteItem getVoteItemFromInv(const CInv &inv) const EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Mutex cs_finalizedItems
Rolling bloom filter to track recently finalized inventory items of any type.
bool sendHelloInternal(CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(cs_delayedAvahelloNodeIds)
int getConfidence(const AnyVoteItem &item) const
bool addToReconcile(const AnyVoteItem &item) EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
std::vector< CInv > getInvsForNextPoll(bool forPoll=true) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
RWCollection< QuerySet > queries
bool hasFinalizedTip() const EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizationTip)
Whether there is a finalized tip.
Mutex cs_stakeContenderCache
bool registerVotes(NodeId nodeid, const Response &response, std::vector< VoteItemUpdate > &updates, int &banscore, std::string &error) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
void transactionAddedToMempool(const CTransactionRef &tx) EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
bool sendHello(CNode *pfrom) EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
Send a avahello message.
bool isRecentlyFinalized(const uint256 &itemId) const EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
bool startEventLoop(CScheduler &scheduler)
bool isQuorumEstablished() LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
void promoteStakeContendersToTip() EXCLUSIVE_LOCKS_REQUIRED(!cs_stakeContenderCache
Promote stake contender cache entries to the latest chain tip.
std::atomic< uint64_t > round
Keep track of peers and queries sent.
bool canShareLocalProof()
static std::unique_ptr< Processor > MakeProcessor(const ArgsManager &argsman, interfaces::Chain &chain, CConnman *connman, ChainstateManager &chainman, CTxMemPool *mempoolIn, CScheduler &scheduler, bilingual_str &error)
EventLoop eventLoop
Event loop machinery.
int64_t minAvaproofsNodeCount
const bool m_preConsensus
Mutex cs_delayedAvahelloNodeIds
bool setStakingRewardWinners(const CBlockIndex *pprev, const std::vector< CScript > &payouts) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards
void runEventLoop() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Mutex cs_invalidatedBlocks
We don't need many blocks but a low false positive rate.
void updatedBlockTip() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
RWCollection< VoteMap > voteRecords
Items to run avalanche on.
void setContenderStatusForLocalWinner(const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakeContenderCache
Helper to set the local winner in the contender cache.
std::unique_ptr< interfaces::Handler > chainNotificationsHandler
uint32_t minQuorumScore
Quorum management.
void FinalizeNode(const ::Config &config, const CNode &node) override LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
Handle removal of a node.
bool getStakingRewardWinners(const BlockHash &prevBlockHash, std::vector< std::pair< ProofId, CScript > > &winners) const EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards)
std::atomic< bool > m_canShareLocalProof
void cleanupStakingRewards(const int minHeight) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards
bool isAccepted(const AnyVoteItem &item) const
ProofRef getLocalProof() const
void addStakeContender(const ProofRef &proof) EXCLUSIVE_LOCKS_REQUIRED(cs_main
Track votes on stake contenders.
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...
const uint32_t staleVoteFactor
void sendDelayedAvahello() EXCLUSIVE_LOCKS_REQUIRED(!cs_delayedAvahelloNodeIds)
std::unique_ptr< PeerData > peerData
bool eraseStakingRewardWinner(const BlockHash &prevBlockHash) EXCLUSIVE_LOCKS_REQUIRED(!cs_stakingRewards)
const bool m_stakingPreConsensus
bool isWorthPolling(const AnyVoteItem &item) const EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
CPubKey getSessionPubKey() const
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, bool stakingPreConsensus)
ChainstateManager & chainman
std::atomic< int64_t > avaproofsNodeCounter
bool computeStakingReward(const CBlockIndex *pindex) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager
ProofRegistrationState getLocalProofRegistrationState() const
int getStakeContenderStatus(const StakeContenderId &contenderId) const EXCLUSIVE_LOCKS_REQUIRED(!cs_stakeContenderCache
void clearTimedoutRequests() EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
Mutex cs_peerManager
Keep track of the peers and associated infos.
bool getLocalAcceptance(const AnyVoteItem &item) const
void avaproofsSent(NodeId nodeid) LOCKS_EXCLUDED(cs_main) EXCLUSIVE_LOCKS_REQUIRED(!cs_peerManager)
double minQuorumConnectedScoreRatio
void clearFinalizedItems() EXCLUSIVE_LOCKS_REQUIRED(!cs_finalizedItems)
static bool FromHex(Proof &proof, const std::string &hexProof, bilingual_str &errorOut)
bool verify(const Amount &stakeUtxoDustThreshold, ProofValidationState &state) const
static uint32_t amountToScore(Amount amount)
uint32_t GetError() const
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Interface giving clients (wallet processes, maybe other analysis tools in the future) ability to acce...
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)
static const uint256 ZERO
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
std::array< uint8_t, CPubKey::SCHNORR_SIZE > SchnorrSig
a Schnorr signature
CKey DecodeSecret(const std::string &str)
bool error(const char *fmt, const Args &...args)
#define LogPrint(category,...)
bool ParseMoney(const std::string &money_string, Amount &nRet)
Parse an amount denoted in full coins.
const char * AVAHELLO
Contains a delegation and a signature.
const char * AVARESPONSE
Contains an avalanche::Response.
const char * AVAPOLL
Contains an avalanche::Poll.
static constexpr Amount PROOF_DUST_THRESHOLD
Minimum amount per utxo.
@ INVALID_STAKE_SIGNATURE
static bool VerifyDelegation(const Delegation &dg, const CPubKey &expectedPubKey, bilingual_str &error)
static bool isNull(const AnyVoteItem &item)
std::variant< const ProofRef, const CBlockIndex *, const CTransactionRef > AnyVoteItem
static const uint256 GetVoteItemId(const AnyVoteItem &item)
static bool VerifyProof(const Amount &stakeUtxoDustThreshold, const Proof &proof, bilingual_str &error)
RCUPtr< const Proof > ProofRef
Implement std::hash so RCUPtr can be used as a key for maps or sets.
static constexpr NodeId NO_NODE
Special NodeId that represent no node.
std::shared_ptr< const CTransaction > CTransactionRef
static const std::string AVAPEERS_FILE_NAME
static constexpr std::chrono::milliseconds AVALANCHE_TIME_STEP
Run the avalanche event loop every 10ms.
static constexpr std::chrono::milliseconds AVALANCHE_DEFAULT_QUERY_TIMEOUT
How long before we consider that a query timed out.
static constexpr size_t AVALANCHE_MAX_ELEMENT_POLL
Maximum item that can be polled at once.
static constexpr int AVALANCHE_MAX_PROOF_STAKES
How many UTXOs can be used for a single proof.
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
#define SERIALIZE_METHODS(cls, obj)
Implement the Serialize and Unserialize methods by delegating to a single templated static method tha...
bool IsStakingRewardsActivated(const Consensus::Params ¶ms, const CBlockIndex *pprev)
A BlockHash is a unqiue identifier for a block.
bool stopEventLoop() EXCLUSIVE_LOCKS_REQUIRED(!cs_running)
bool startEventLoop(CScheduler &scheduler, std::function< void()> runEventLoop, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!cs_running)
A TxId is the identifier of a transaction.
const std::chrono::milliseconds queryTimeoutDuration
bool operator()(const CBlockIndex *pindex) const LOCKS_EXCLUDED(cs_main)
const Processor & processor
bool operator()(const CBlockIndex *pindex) const LOCKS_EXCLUDED(cs_main)
ProofRegistrationState proofState GUARDED_BY(cs_proofState)
StakeContenderIds are unique for each block to ensure that the peer polling for their acceptance has ...
#define AssertLockNotHeld(cs)
#define WITH_LOCK(cs, code)
Run code while locking a mutex.
#define AssertLockHeld(cs)
#define EXCLUSIVE_LOCKS_REQUIRED(...)
bilingual_str _(const char *psz)
Translation function.
bool ParseFixedPoint(std::string_view val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
static constexpr uint32_t AVALANCHE_VOTE_STALE_FACTOR
Scaling factor applied to confidence to determine staleness threshold.
static constexpr uint32_t AVALANCHE_VOTE_STALE_MIN_THRESHOLD
Lowest configurable staleness threshold (finalization score + necessary votes to increase confidence ...
static constexpr uint32_t AVALANCHE_VOTE_STALE_THRESHOLD
Number of votes before a record may be considered as stale.