diff --git a/src/rpc/avalanche.cpp b/src/rpc/avalanche.cpp --- a/src/rpc/avalanche.cpp +++ b/src/rpc/avalanche.cpp @@ -73,6 +73,24 @@ } } +static void verifyProofOrThrow(const NodeContext &node, avalanche::Proof &proof, + const std::string &proofHex) { + bilingual_str error; + if (!avalanche::Proof::FromHex(proof, proofHex, error)) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, error.original); + } + + avalanche::ProofValidationState state; + { + LOCK(cs_main); + if (!proof.verify(state, + node.chainman->ActiveChainstate().CoinsTip())) { + throw JSONRPCError(RPC_INVALID_PARAMETER, + "The proof is invalid: " + state.ToString()); + } + } +} + static UniValue addavalanchenode(const Config &config, const JSONRPCRequest &request) { RPCHelpMan{ @@ -106,11 +124,8 @@ CPubKey key = ParsePubKey(request.params[1]); auto proof = std::make_shared(); - bilingual_str error; - if (!avalanche::Proof::FromHex(*proof, request.params[2].get_str(), - error)) { - throw JSONRPCError(RPC_DESERIALIZATION_ERROR, error.original); - } + NodeContext &node = EnsureNodeContext(request.context); + verifyProofOrThrow(node, *proof, request.params[2].get_str()); const avalanche::ProofId &proofid = proof->getId(); if (key != proof->getMaster()) { @@ -135,10 +150,10 @@ } if (!registerProofIfNeeded(proof)) { - return false; + throw JSONRPCError(RPC_INVALID_PARAMETER, + "The proof has conflicting utxos"); } - NodeContext &node = EnsureNodeContext(request.context); if (!node.connman->ForNode(nodeid, [&](CNode *pnode) { // FIXME This is not thread safe, and might cause issues if the // unlikely event the peer sends an avahello message at the same @@ -150,7 +165,9 @@ pnode->m_avalanche_state->pubkey = std::move(key); return true; })) { - return false; + throw JSONRPCError(RPC_INVALID_PARAMETER, + strprintf("The node does not exist: %d", nodeid)); + ; } return g_avalanche->withPeerManager([&](avalanche::PeerManager &pm) { @@ -557,24 +574,6 @@ return ret; } -static void verifyProofOrThrow(const NodeContext &node, avalanche::Proof &proof, - const std::string &proofHex) { - bilingual_str error; - if (!avalanche::Proof::FromHex(proof, proofHex, error)) { - throw JSONRPCError(RPC_DESERIALIZATION_ERROR, error.original); - } - - avalanche::ProofValidationState state; - { - LOCK(cs_main); - if (!proof.verify(state, - node.chainman->ActiveChainstate().CoinsTip())) { - throw JSONRPCError(RPC_INVALID_PARAMETER, - "The proof is invalid: " + state.ToString()); - } - } -} - static UniValue sendavalancheproof(const Config &config, const JSONRPCRequest &request) { RPCHelpMan{ diff --git a/test/functional/abc_rpc_addavalanchenode.py b/test/functional/abc_rpc_addavalanchenode.py --- a/test/functional/abc_rpc_addavalanchenode.py +++ b/test/functional/abc_rpc_addavalanchenode.py @@ -55,7 +55,7 @@ nodeid = add_interface_node(node) def check_addavalanchenode_error( - error_code, error_message, proof=proof, pubkey=proof_master, delegation=None): + error_code, error_message, nodeid=nodeid, proof=proof, pubkey=proof_master, delegation=None): assert_raises_rpc_error( error_code, error_message, @@ -75,10 +75,14 @@ proof="f000") no_stake = node.buildavalancheproof( proof_sequence, proof_expiration, proof_master, []) - assert not node.addavalanchenode(nodeid, proof_master, no_stake) + check_addavalanchenode_error(-8, + "The proof is invalid: no-stake", + proof=no_stake) self.log.info("Node doesn't exist") - assert not node.addavalanchenode(nodeid + 1, proof_master, proof) + check_addavalanchenode_error(-8, + f"The node does not exist: {nodeid + 1}", + nodeid=nodeid + 1) self.log.info("Invalid delegation") dg_privkey = ECKey()