diff --git a/src/avalanche/processor.h b/src/avalanche/processor.h --- a/src/avalanche/processor.h +++ b/src/avalanche/processor.h @@ -195,6 +195,15 @@ struct AvalancheTest; } +struct PeerData { + std::optional proof; + std::optional delegation; + CKey sessionKey; + + static bool FromArgs(PeerData &peerData, const ArgsManager &argsman, + bilingual_str &error); +}; + class Processor { CConnman *connman; NodePeerManager *nodePeerManager; @@ -247,13 +256,6 @@ RWCollection queries; /** Data required to participate. */ - struct PeerData { - std::optional proof; - std::optional delegation; - CKey sessionKey; - - static PeerData FromArgs(const ArgsManager &argsman); - }; PeerData peerData; /** Event loop machinery. */ @@ -273,7 +275,7 @@ Processor(interfaces::Chain &chain, CConnman *connmanIn, NodePeerManager *nodePeerManagerIn); Processor(interfaces::Chain &chain, CConnman *connmanIn, - NodePeerManager *nodePeerManagerIn, const ArgsManager &argsman); + NodePeerManager *nodePeerManagerIn, const PeerData &peerDataIn); ~Processor(); void setQueryTimeoutDuration(std::chrono::milliseconds d) { diff --git a/src/avalanche/processor.cpp b/src/avalanche/processor.cpp --- a/src/avalanche/processor.cpp +++ b/src/avalanche/processor.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -136,9 +137,8 @@ return true; } -Processor::PeerData Processor::PeerData::FromArgs(const ArgsManager &argsman) { - PeerData peerData; - +bool PeerData::FromArgs(PeerData &peerData, const ArgsManager &argsman, + bilingual_str &error) { if (argsman.IsArgSet("-avasessionkey")) { peerData.sessionKey = DecodeSecret(argsman.GetArg("-avasessionkey", "")); @@ -154,6 +154,37 @@ SER_NETWORK, 0); Proof proof; stream >> proof; + + // If a proof is supplied, make sure it does not contain garbage. + // At this point the validity of the utxos cannot be checked, so + // only basic verification is performed. + avalanche::ProofValidationState proof_state; + if (!proof.verify(proof_state)) { + switch (proof_state.GetResult()) { + case avalanche::ProofValidationResult::NO_STAKE: + error = _("the avalanche proof has no stake"); + return false; + case avalanche::ProofValidationResult::DUST_THRESOLD: + error = _("the avalanche proof stake is too low"); + return false; + case avalanche::ProofValidationResult::DUPLICATE_STAKE: + error = _("the avalanche proof has duplicated stake"); + return false; + case avalanche::ProofValidationResult::INVALID_SIGNATURE: + error = _("the avalanche proof has invalid stake " + "signatures"); + return false; + case avalanche::ProofValidationResult::TOO_MANY_UTXOS: + error = strprintf(_("the avalanche proof has too " + "many utxos (max: %u)"), + AVALANCHE_MAX_PROOF_STAKES); + return false; + default: + error = _("the avalanche proof is invalid"); + return false; + } + } + peerData.proof = proof; } @@ -166,7 +197,7 @@ peerData.delegation = dgb.build(); } - return peerData; + return true; } class Processor::NotificationsHandler @@ -202,9 +233,9 @@ Processor::Processor(interfaces::Chain &chain, CConnman *connmanIn, NodePeerManager *nodePeerManagerIn, - const ArgsManager &argsman) + const PeerData &peerDataIn) : Processor(chain, connmanIn, nodePeerManagerIn) { - peerData = PeerData::FromArgs(argsman); + peerData = peerDataIn; if (peerData.proof) { // Schedule proof registration at the first new block after IBD. diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -2437,47 +2437,24 @@ } // Step 6.5 (I guess ?): Initialize Avalanche. - g_avalanche = std::make_unique( - *node.chain, node.connman.get(), node.peerman.get(), args); + { + avalanche::PeerData peerData; + bilingual_str avaErrorStr; + if (!avalanche::PeerData::FromArgs(peerData, args, avaErrorStr)) { + InitError(avaErrorStr); + return false; + } + + g_avalanche = std::make_unique( + *node.chain, node.connman.get(), node.peerman.get(), peerData); + } + if (args.GetBoolArg("-enableavalanche", AVALANCHE_DEFAULT_ENABLED)) { nLocalServices = ServiceFlags(nLocalServices | NODE_AVALANCHE); - // If avalanche is enabled and a proof is supplied, make sure it does - // not contain garbage. At this point the validity of the utxos cannot - // be checked, so only basic verification is performed. - const std::optional proof = g_avalanche->getProof(); - - if (!proof) { + if (!g_avalanche->getProof()) { LogPrintf("Avalanche is enabled but no proof supplied, the node " "will not be able to vote\n"); - } else { - avalanche::ProofValidationState proof_state; - if (!proof->verify(proof_state)) { - switch (proof_state.GetResult()) { - case avalanche::ProofValidationResult::NO_STAKE: - InitError(_("the avalanche proof has no stake")); - return false; - case avalanche::ProofValidationResult::DUST_THRESOLD: - InitError(_("the avalanche proof stake is too low")); - return false; - case avalanche::ProofValidationResult::DUPLICATE_STAKE: - InitError( - _("the avalanche proof has duplicated stake")); - return false; - case avalanche::ProofValidationResult::INVALID_SIGNATURE: - InitError(_("the avalanche proof has invalid stake " - "signatures")); - return false; - case avalanche::ProofValidationResult::TOO_MANY_UTXOS: - InitError(strprintf(_("the avalanche proof has too " - "many utxos (max: %u)"), - AVALANCHE_MAX_PROOF_STAKES)); - return false; - default: - InitError(_("the avalanche proof is invalid")); - return false; - } - } } }