LCOV - code coverage report
Current view: top level - src/rpc - util.h (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 64 70 91.4 %
Date: 2026-06-25 07:23:51 Functions: 44 49 89.8 %

          Line data    Source code
       1             : // Copyright (c) 2017-2020 The Bitcoin Core 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             : #ifndef BITCOIN_RPC_UTIL_H
       6             : #define BITCOIN_RPC_UTIL_H
       7             : 
       8             : #include <consensus/amount.h>
       9             : #include <node/transaction.h>
      10             : #include <pubkey.h>
      11             : #include <rpc/protocol.h>
      12             : #include <rpc/request.h>
      13             : #include <script/script.h>
      14             : #include <script/sign.h>
      15             : #include <script/signingprovider.h>
      16             : #include <script/standard.h>
      17             : #include <uint256.h>
      18             : #include <univalue.h>
      19             : #include <util/check.h>
      20             : #include <util/strencodings.h>
      21             : 
      22             : #include <cstddef>
      23             : #include <cstdint>
      24             : #include <functional>
      25             : #include <initializer_list>
      26             : #include <map>
      27             : #include <optional>
      28             : #include <string>
      29             : #include <type_traits>
      30             : #include <utility>
      31             : #include <variant>
      32             : #include <vector>
      33             : 
      34             : class JSONRPCRequest;
      35             : enum ServiceFlags : uint64_t;
      36             : enum class OutputType;
      37             : enum class TransactionError;
      38             : struct FlatSigningProvider;
      39             : struct bilingual_str;
      40             : 
      41             : static constexpr bool DEFAULT_RPC_DOC_CHECK{
      42             : #ifdef RPC_DOC_CHECK
      43             :     true
      44             : #else
      45             :     false
      46             : #endif
      47             : };
      48             : 
      49             : /**
      50             :  * String used to describe UNIX epoch time in documentation, factored out to a
      51             :  * constant for consistency.
      52             :  */
      53             : extern const std::string UNIX_EPOCH_TIME;
      54             : 
      55             : /**
      56             :  * Example Dash addresses for the RPCExamples help documentation. They are intentionally
      57             :  * invalid to prevent accidental transactions by users.
      58             :  */
      59             : extern const std::string EXAMPLE_ADDRESS[2];
      60             : 
      61             : class FillableSigningProvider;
      62             : class FillableSigningProvider;
      63             : class CScript;
      64             : struct Sections;
      65             : 
      66             : /**
      67             :  * Gets all existing output types formatted for RPC help sections.
      68             :  *
      69             :  * @return Comma separated string representing output type names.
      70             :  */
      71             : std::string GetAllOutputTypes();
      72             : 
      73             : /** Wrapper for UniValue::VType, which includes typeAny:
      74             :  * Used to denote don't care type. */
      75             : struct UniValueType {
      76          90 :     UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {}
      77          22 :     UniValueType() : typeAny(true) {}
      78             :     bool typeAny;
      79             :     UniValue::VType type;
      80             : };
      81             : 
      82             : /**
      83             :  * Type-check arguments; throws JSONRPCError if wrong type given. Does not check that
      84             :  * the right number of arguments are passed, just that any passed are the correct type.
      85             :  */
      86             : void RPCTypeCheck(const UniValue& params,
      87             :                   const std::list<UniValueType>& typesExpected, bool fAllowNull=false);
      88             : 
      89             : /**
      90             :  * Type-check one argument; throws JSONRPCError if wrong type given.
      91             :  */
      92             : void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected);
      93             : 
      94             : /*
      95             :   Check for expected keys/value types in an Object.
      96             : */
      97             : void RPCTypeCheckObj(const UniValue& o,
      98             :     const std::map<std::string, UniValueType>& typesExpected,
      99             :     bool fAllowNull = false,
     100             :     bool fStrict = false);
     101             : 
     102             : /**
     103             :  * Utilities: convert hex-encoded Values
     104             :  * (throws error if not hex).
     105             :  */
     106             : uint256 ParseHashV(const UniValue& v, std::string strName);
     107             : uint256 ParseHashO(const UniValue& o, std::string strKey);
     108             : std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
     109             : std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
     110             : 
     111             : bool ParseBoolV(const UniValue& v, const std::string &strName);
     112             : 
     113             : /**
     114             :  * Validate and return a CAmount from a UniValue number or string.
     115             :  *
     116             :  * @param[in] value     UniValue number or string to parse.
     117             :  * @param[in] decimals  Number of significant digits (default: 8).
     118             :  * @returns a CAmount if the various checks pass.
     119             :  */
     120             : CAmount AmountFromValue(const UniValue& value, int decimals = 8);
     121             : 
     122             : using RPCArgList = std::vector<std::pair<std::string, UniValue>>;
     123             : std::string HelpExampleCli(const std::string& methodname, const std::string& args);
     124             : std::string HelpExampleCliNamed(const std::string& methodname, const RPCArgList& args);
     125             : std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
     126             : std::string HelpExampleRpcNamed(const std::string& methodname, const RPCArgList& args);
     127             : 
     128             : CPubKey HexToPubKey(const std::string& hex_in);
     129             : CPubKey AddrToPubKey(const FillableSigningProvider& keystore, const std::string& addr_in);
     130             : CTxDestination AddAndGetMultisigDestination(const int required, const std::vector<CPubKey>& pubkeys, FillableSigningProvider& keystore, CScript& script_out);
     131             : 
     132             : UniValue DescribeAddress(const CTxDestination& dest);
     133             : 
     134             : //! Parse a confirm target option and raise an RPC error if it is invalid.
     135             : unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target);
     136             : 
     137             : 
     138             : //! Parse a JSON range specified as int64, or [int64, int64]
     139             : std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue& value);
     140             : 
     141             : /**
     142             :  * Serializing JSON objects depends on the outer type. Only arrays and
     143             :  * dictionaries can be nested in json. The top-level outer type is "NONE".
     144             :  */
     145             : enum class OuterType {
     146             :     ARR,
     147             :     OBJ,
     148             :     NONE, // Only set on first recursion
     149             : };
     150             : /** Evaluate a descriptor given as a string, or as a {"desc":...,"range":...} object, with default range of 1000. */
     151             : std::vector<CScript> EvalDescriptorStringOrObject(const UniValue& scanobject, FlatSigningProvider& provider);
     152             : 
     153       58150 : struct RPCArg {
     154             :     enum class Type {
     155             :         OBJ,
     156             :         ARR,
     157             :         STR,
     158             :         NUM,
     159             :         BOOL,
     160             :         OBJ_USER_KEYS, //!< Special type where the user must set the keys e.g. to define multiple addresses; as opposed to e.g. an options object where the keys are predefined
     161             :         AMOUNT,        //!< Special type representing a floating point amount (can be either NUM or STR)
     162             :         STR_HEX,       //!< Special type that is a STR with only hex chars
     163             :         RANGE,         //!< Special type that is a NUM or [NUM,NUM]
     164             :     };
     165             : 
     166             :     enum class Optional {
     167             :         /** Required arg */
     168             :         NO,
     169             :         /**
     170             :          * The arg is optional for one of two reasons:
     171             :          *
     172             :          * Optional arg that is a named argument and has a default value of
     173             :          * `null`.
     174             :          *
     175             :          * Optional argument with default value omitted because they are
     176             :          * implicitly clear. That is, elements in an array may not
     177             :          * exist by default.
     178             :          * When possible, the default value should be specified.
     179             :          */
     180             :         OMITTED,
     181             :         OMITTED_NAMED_ARG, // Deprecated alias for OMITTED, can be removed
     182             :     };
     183             :     /** Hint for default value */
     184             :     using DefaultHint = std::string;
     185             :     /** Default constant value */
     186             :     using Default = UniValue;
     187             :     using Fallback = std::variant<Optional, DefaultHint, Default>;
     188             : 
     189             :     const std::string m_names; //!< The name of the arg (can be empty for inner args, can contain multiple aliases separated by | for named request arguments)
     190             :     const Type m_type;
     191             :     const bool m_hidden;
     192             :     const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts
     193             :     const Fallback m_fallback;
     194             :     const std::string m_description;
     195             :     const std::string m_oneline_description; //!< Should be empty unless it is supposed to override the auto-generated summary line
     196             :     const std::vector<std::string> m_type_str; //!< Should be empty unless it is supposed to override the auto-generated type strings. Vector length is either 0 or 2, m_type_str.at(0) will override the type of the value in a key-value pair, m_type_str.at(1) will override the type in the argument description.
     197             : 
     198      120675 :     RPCArg(
     199             :         std::string name,
     200             :         Type type,
     201             :         Fallback fallback,
     202             :         std::string description,
     203             :         std::string oneline_description = "",
     204             :         std::vector<std::string> type_str = {},
     205             :         bool hidden = false)
     206       40225 :         : m_names{std::move(name)},
     207       40225 :           m_type{std::move(type)},
     208       40225 :           m_hidden{hidden},
     209       40225 :           m_fallback{std::move(fallback)},
     210       40225 :           m_description{std::move(description)},
     211       40225 :           m_oneline_description{std::move(oneline_description)},
     212       40225 :           m_type_str{std::move(type_str)}
     213       40225 :     {
     214       40225 :         CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ && type != Type::OBJ_USER_KEYS);
     215       80450 :     }
     216             : 
     217        9856 :     RPCArg(
     218             :         std::string name,
     219             :         Type type,
     220             :         Fallback fallback,
     221             :         std::string description,
     222             :         std::vector<RPCArg> inner,
     223             :         std::string oneline_description = "",
     224             :         std::vector<std::string> type_str = {})
     225        4928 :         : m_names{std::move(name)},
     226        4928 :           m_type{std::move(type)},
     227        4928 :           m_hidden{false},
     228        4928 :           m_inner{std::move(inner)},
     229        4928 :           m_fallback{std::move(fallback)},
     230        4928 :           m_description{std::move(description)},
     231        4928 :           m_oneline_description{std::move(oneline_description)},
     232        4928 :           m_type_str{std::move(type_str)}
     233        4928 :     {
     234        4928 :         CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ || type == Type::OBJ_USER_KEYS);
     235        9856 :     }
     236             : 
     237             :     bool IsOptional() const;
     238             : 
     239             :     /** Return the first of all aliases */
     240             :     std::string GetFirstName() const;
     241             : 
     242             :     /** Return the name, throws when there are aliases */
     243             :     std::string GetName() const;
     244             : 
     245             :     /**
     246             :      * Return the type string of the argument.
     247             :      * Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description).
     248             :      */
     249             :     std::string ToString(bool oneline) const;
     250             :     /**
     251             :      * Return the type string of the argument when it is in an object (dict).
     252             :      * Set oneline to get the oneline representation (less whitespace)
     253             :      */
     254             :     std::string ToStringObj(bool oneline) const;
     255             :     /**
     256             :      * Return the description string, including the argument type and whether
     257             :      * the argument is required.
     258             :      */
     259             :     std::string ToDescriptionString(bool is_named_arg) const;
     260             : };
     261             : 
     262     1386569 : struct RPCResult {
     263             :     enum class Type {
     264             :         OBJ,
     265             :         ARR,
     266             :         STR,
     267             :         NUM,
     268             :         BOOL,
     269             :         NONE,
     270             :         ANY,        //!< Special type to disable type checks (for testing only)
     271             :         STR_AMOUNT, //!< Special string to represent a floating point amount
     272             :         STR_HEX,    //!< Special string with only hex chars
     273             :         OBJ_DYN,    //!< Special dictionary with keys that are not literals
     274             :         ARR_FIXED,  //!< Special array that has a fixed number of entries
     275             :         NUM_TIME,   //!< Special numeric to denote unix epoch time
     276             :         ELISION,    //!< Special type to denote elision (...)
     277             :     };
     278             : 
     279             :     const Type m_type;
     280             :     const std::string m_key_name;         //!< Only used for dicts
     281             :     const std::vector<RPCResult> m_inner; //!< Only used for arrays or dicts
     282             :     const bool m_optional;
     283             :     const std::string m_description;
     284             :     const std::string m_cond;
     285             : 
     286       17768 :     RPCResult(
     287             :         std::string cond,
     288             :         Type type,
     289             :         std::string m_key_name,
     290             :         bool optional,
     291             :         std::string description,
     292             :         std::vector<RPCResult> inner = {})
     293        8884 :         : m_type{std::move(type)},
     294        8884 :           m_key_name{std::move(m_key_name)},
     295        8884 :           m_inner{std::move(inner)},
     296        8884 :           m_optional{optional},
     297        8884 :           m_description{std::move(description)},
     298        8884 :           m_cond{std::move(cond)}
     299        8884 :     {
     300        8884 :         CHECK_NONFATAL(!m_cond.empty());
     301        8884 :         CheckInnerDoc();
     302       17768 :     }
     303             : 
     304        8884 :     RPCResult(
     305             :         std::string cond,
     306             :         Type type,
     307             :         std::string m_key_name,
     308             :         std::string description,
     309             :         std::vector<RPCResult> inner = {})
     310        8884 :         : RPCResult{std::move(cond), type, std::move(m_key_name), /*optional=*/false, std::move(description), std::move(inner)} {}
     311             : 
     312      423706 :     RPCResult(
     313             :         Type type,
     314             :         std::string m_key_name,
     315             :         bool optional,
     316             :         std::string description,
     317             :         std::vector<RPCResult> inner = {})
     318      211853 :         : m_type{std::move(type)},
     319      211853 :           m_key_name{std::move(m_key_name)},
     320      211853 :           m_inner{std::move(inner)},
     321      211853 :           m_optional{optional},
     322      211853 :           m_description{std::move(description)},
     323      211853 :           m_cond{}
     324      211853 :     {
     325      211853 :         CheckInnerDoc();
     326      423706 :     }
     327             : 
     328      153145 :     RPCResult(
     329             :         Type type,
     330             :         std::string m_key_name,
     331             :         std::string description,
     332             :         std::vector<RPCResult> inner = {})
     333      153145 :         : RPCResult{type, m_key_name, false, description, inner} {}
     334             : 
     335             :     /** Append the sections of the result. */
     336             :     void ToSections(Sections& sections, OuterType outer_type = OuterType::NONE, const int current_indent = 0) const;
     337             :     /** Return the type string of the result when it is in an object (dict). */
     338             :     std::string ToStringObj() const;
     339             :     /** Return the description string, including the result type. */
     340             :     std::string ToDescriptionString() const;
     341             :     /** Check whether the result JSON type matches. */
     342             :     bool MatchesType(const UniValue& result) const;
     343             : 
     344             : private:
     345             :     void CheckInnerDoc() const;
     346             : };
     347             : 
     348             : struct RPCResults {
     349             :     const std::vector<RPCResult> m_results;
     350             : 
     351       42254 :     RPCResults(RPCResult result)
     352       21127 :         : m_results{{result}}
     353       21127 :     {
     354       42254 :     }
     355             : 
     356        4592 :     RPCResults(std::initializer_list<RPCResult> results)
     357        2296 :         : m_results{results}
     358        2296 :     {
     359        4592 :     }
     360             : 
     361             :     /**
     362             :      * Return the description string.
     363             :      */
     364             :     std::string ToDescriptionString() const;
     365             : };
     366             : 
     367             : struct RPCExamples {
     368             :     const std::string m_examples;
     369       46922 :     explicit RPCExamples(
     370             :         std::string examples)
     371       23461 :         : m_examples(std::move(examples))
     372       23461 :     {
     373       46922 :     }
     374             :     std::string ToDescriptionString() const;
     375             : };
     376             : 
     377             : class RPCHelpMan
     378             : {
     379             : public:
     380             :     RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples);
     381             :     using RPCMethodImpl = std::function<UniValue(const RPCHelpMan&, const JSONRPCRequest&)>;
     382             :     RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun);
     383             : 
     384             :     UniValue HandleRequest(const JSONRPCRequest& request) const;
     385             :     /**
     386             :      * Helper to get a request argument.
     387             :      * This function only works during m_fun(), i.e. it should only be used in
     388             :      * RPC method implementations. The helper internally checks whether the
     389             :      * user-passed argument isNull() and parses (from JSON) and returns the
     390             :      * user-passed argument, or the default value derived from the RPCArg
     391             :      * documention, or a falsy value if no default was given.
     392             :      *
     393             :      * Use Arg<Type>(i) to get the argument or its default value. Otherwise,
     394             :      * use MaybeArg<Type>(i) to get the optional argument or a falsy value.
     395             :      *
     396             :      * The Type passed to this helper must match the corresponding
     397             :      * RPCArg::Type.
     398             :      */
     399             :     template <typename R>
     400           0 :     auto Arg(size_t i) const
     401             :     {
     402             :         // Return argument (required or with default value).
     403             :         if constexpr (std::is_integral_v<R> || std::is_floating_point_v<R>) {
     404             :             // Return numbers by value.
     405           0 :             return ArgValue<R>(i);
     406             :         } else {
     407             :             // Return everything else by reference.
     408           0 :             return ArgValue<const R&>(i);
     409             :         }
     410             :     }
     411             :     template <typename R>
     412           0 :     auto MaybeArg(size_t i) const
     413             :     {
     414             :         // Return optional argument (without default).
     415             :         if constexpr (std::is_integral_v<R> || std::is_floating_point_v<R>) {
     416             :             // Return numbers by value, wrapped in optional.
     417           0 :             return ArgValue<std::optional<R>>(i);
     418             :         } else {
     419             :             // Return other types by pointer.
     420           0 :             return ArgValue<const R*>(i);
     421             :         }
     422             :     }
     423             :     std::string ToString() const;
     424             :     /** Return the named args that need to be converted from string to another JSON type */
     425             :     UniValue GetArgMap() const;
     426             :     /** If the supplied number of args is neither too small nor too high */
     427             :     bool IsValidNumArgs(size_t num_args) const;
     428             : 
     429             :     std::vector<std::string> GetArgNames() const;
     430             : 
     431             :     const std::string m_name;
     432             : 
     433             : private:
     434             :     const RPCMethodImpl m_fun;
     435             :     const std::string m_description;
     436             :     const std::vector<RPCArg> m_args;
     437             :     const RPCResults m_results;
     438             :     const RPCExamples m_examples;
     439             :     mutable const JSONRPCRequest* m_req{nullptr}; // A pointer to the request for the duration of m_fun()
     440             :     template <typename R>
     441             :     R ArgValue(size_t i) const;
     442             : };
     443             : 
     444             : RPCErrorCode RPCErrorFromTransactionError(TransactionError terr);
     445             : UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_string = "");
     446             : 
     447             : #endif // BITCOIN_RPC_UTIL_H

Generated by: LCOV version 1.16