diff --git a/src/avalanche/delegation.h b/src/avalanche/delegation.h --- a/src/avalanche/delegation.h +++ b/src/avalanche/delegation.h @@ -13,6 +13,8 @@ #include +struct bilingual_str; + namespace avalanche { class DelegationState; @@ -44,6 +46,9 @@ public: explicit Delegation() {} + static bool FromHex(Delegation &dg, const std::string &dgHex, + bilingual_str &errorOut); + const DelegationId &getId() const { return dgid; } const LimitedProofId &getLimitedProofId() const { return limitedProofid; } const CPubKey &getProofMaster() const { return proofMaster; } diff --git a/src/avalanche/delegation.cpp b/src/avalanche/delegation.cpp --- a/src/avalanche/delegation.cpp +++ b/src/avalanche/delegation.cpp @@ -7,9 +7,31 @@ #include #include #include +#include +#include +#include namespace avalanche { +bool Delegation::FromHex(Delegation &dg, const std::string &dgHex, + bilingual_str &errorOut) { + if (!IsHex(dgHex)) { + errorOut = _("Delegation must be an hexadecimal string."); + return false; + } + + CDataStream ss(ParseHex(dgHex), SER_NETWORK, PROTOCOL_VERSION); + + try { + ss >> dg; + } catch (std::exception &e) { + errorOut = strprintf(_("Delegation has invalid format: %s"), e.what()); + return false; + } + + return true; +} + template static bool reduceLevels(uint256 &hash, const std::vector &levels, F f) { for (const auto &l : levels) { diff --git a/src/rpc/avalanche.cpp b/src/rpc/avalanche.cpp --- a/src/rpc/avalanche.cpp +++ b/src/rpc/avalanche.cpp @@ -343,9 +343,11 @@ std::unique_ptr dgb; if (request.params.size() >= 4 && !request.params[3].isNull()) { avalanche::Delegation dg; - CDataStream ss(ParseHexV(request.params[3], "delegation"), SER_NETWORK, - PROTOCOL_VERSION); - ss >> dg; + bilingual_str error; + if (!avalanche::Delegation::FromHex(dg, request.params[3].get_str(), + error)) { + throw JSONRPCError(RPC_DESERIALIZATION_ERROR, error.original); + } if (dg.getProofId() != limitedProofId.computeProofId(dg.getProofMaster())) { diff --git a/test/functional/abc_rpc_avalancheproof.py b/test/functional/abc_rpc_avalancheproof.py --- a/test/functional/abc_rpc_avalancheproof.py +++ b/test/functional/abc_rpc_avalancheproof.py @@ -211,6 +211,23 @@ delegation, ) + # Delegation not hex + assert_raises_rpc_error(-22, "Delegation must be an hexadecimal string.", + node.delegateavalancheproof, + limited_id_hex, + bytes_to_wif(privkey.get_bytes()), + random_pubkey, + "f00", + ) + # Delegation is hex but ill-formed + assert_raises_rpc_error(-22, "Delegation has invalid format", + node.delegateavalancheproof, + limited_id_hex, + bytes_to_wif(privkey.get_bytes()), + random_pubkey, + "dead", + ) + # Test invalid proofs dust = node.buildavalancheproof( proof_sequence, proof_expiration, proof_master,