LCOV - code coverage report
Current view: top level - src/rpc - util.h (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 54 62 87.1 %
Date: 2023-09-26 12:08:55 Functions: 22 31 71.0 %

          Line data    Source code
       1             : // Copyright (c) 2017-2022 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 <addresstype.h>
       9             : #include <consensus/amount.h>
      10             : #include <node/transaction.h>
      11             : #include <outputtype.h>
      12             : #include <protocol.h>
      13             : #include <pubkey.h>
      14             : #include <rpc/protocol.h>
      15             : #include <rpc/request.h>
      16             : #include <script/script.h>
      17             : #include <script/sign.h>
      18             : #include <uint256.h>
      19             : #include <univalue.h>
      20             : #include <util/check.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 bech32 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 CPubKey;
      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           0 :     UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {}
      77           0 :     UniValueType() : typeAny(true) {}
      78             :     bool typeAny;
      79             :     UniValue::VType type;
      80             : };
      81             : 
      82             : /*
      83             :   Check for expected keys/value types in an Object.
      84             : */
      85             : void RPCTypeCheckObj(const UniValue& o,
      86             :     const std::map<std::string, UniValueType>& typesExpected,
      87             :     bool fAllowNull = false,
      88             :     bool fStrict = false);
      89             : 
      90             : /**
      91             :  * Utilities: convert hex-encoded Values
      92             :  * (throws error if not hex).
      93             :  */
      94             : uint256 ParseHashV(const UniValue& v, std::string strName);
      95             : uint256 ParseHashO(const UniValue& o, std::string strKey);
      96             : std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
      97             : std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
      98             : 
      99             : /**
     100             :  * Validate and return a CAmount from a UniValue number or string.
     101             :  *
     102             :  * @param[in] value     UniValue number or string to parse.
     103             :  * @param[in] decimals  Number of significant digits (default: 8).
     104             :  * @returns a CAmount if the various checks pass.
     105             :  */
     106             : CAmount AmountFromValue(const UniValue& value, int decimals = 8);
     107             : 
     108             : using RPCArgList = std::vector<std::pair<std::string, UniValue>>;
     109             : std::string HelpExampleCli(const std::string& methodname, const std::string& args);
     110             : std::string HelpExampleCliNamed(const std::string& methodname, const RPCArgList& args);
     111             : std::string HelpExampleRpc(const std::string& methodname, const std::string& args);
     112             : std::string HelpExampleRpcNamed(const std::string& methodname, const RPCArgList& args);
     113             : 
     114             : CPubKey HexToPubKey(const std::string& hex_in);
     115             : CPubKey AddrToPubKey(const FillableSigningProvider& keystore, const std::string& addr_in);
     116             : CTxDestination AddAndGetMultisigDestination(const int required, const std::vector<CPubKey>& pubkeys, OutputType type, FillableSigningProvider& keystore, CScript& script_out);
     117             : 
     118             : UniValue DescribeAddress(const CTxDestination& dest);
     119             : 
     120             : /** Parse a sighash string representation and raise an RPC error if it is invalid. */
     121             : int ParseSighashString(const UniValue& sighash);
     122             : 
     123             : //! Parse a confirm target option and raise an RPC error if it is invalid.
     124             : unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target);
     125             : 
     126             : RPCErrorCode RPCErrorFromTransactionError(TransactionError terr);
     127             : UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_string = "");
     128             : 
     129             : //! Parse a JSON range specified as int64, or [int64, int64]
     130             : std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue& value);
     131             : 
     132             : /** Evaluate a descriptor given as a string, or as a {"desc":...,"range":...} object, with default range of 1000. */
     133             : std::vector<CScript> EvalDescriptorStringOrObject(const UniValue& scanobject, FlatSigningProvider& provider, const bool expand_priv = false);
     134             : 
     135             : /** Returns, given services flags, a list of humanly readable (known) network services */
     136             : UniValue GetServicesNames(ServiceFlags services);
     137             : 
     138             : /**
     139             :  * Serializing JSON objects depends on the outer type. Only arrays and
     140             :  * dictionaries can be nested in json. The top-level outer type is "NONE".
     141             :  */
     142             : enum class OuterType {
     143             :     ARR,
     144             :     OBJ,
     145             :     NONE, // Only set on first recursion
     146             : };
     147             : 
     148         696 : struct RPCArgOptions {
     149             :     bool skip_type_check{false};
     150             :     std::string oneline_description{};   //!< Should be empty unless it is supposed to override the auto-generated summary line
     151             :     std::vector<std::string> type_str{}; //!< Should be empty unless it is supposed to override the auto-generated type strings. Vector length is either 0 or 2, m_opts.type_str.at(0) will override the type of the value in a key-value pair, m_opts.type_str.at(1) will override the type in the argument description.
     152             :     bool hidden{false};                  //!< For testing only
     153             :     bool also_positional{false};         //!< If set allows a named-parameter field in an OBJ_NAMED_PARAM options object
     154             :                                          //!< to have the same name as a top-level parameter. By default the RPC
     155             :                                          //!< framework disallows this, because if an RPC request passes the value by
     156             :                                          //!< name, it is assigned to top-level parameter position, not to the options
     157             :                                          //!< position, defeating the purpose of using OBJ_NAMED_PARAMS instead OBJ for
     158             :                                          //!< that option. But sometimes it makes sense to allow less-commonly used
     159             :                                          //!< options to be passed by name only, and more commonly used options to be
     160             :                                          //!< passed by name or position, so the RPC framework allows this as long as
     161             :                                          //!< methods set the also_positional flag and read values from both positions.
     162             : };
     163             : 
     164         696 : struct RPCArg {
     165             :     enum class Type {
     166             :         OBJ,
     167             :         ARR,
     168             :         STR,
     169             :         NUM,
     170             :         BOOL,
     171             :         OBJ_NAMED_PARAMS, //!< Special type that behaves almost exactly like
     172             :                           //!< OBJ, defining an options object with a list of
     173             :                           //!< pre-defined keys. The only difference between OBJ
     174             :                           //!< and OBJ_NAMED_PARAMS is that OBJ_NAMED_PARMS
     175             :                           //!< also allows the keys to be passed as top-level
     176             :                           //!< named parameters, as a more convenient way to pass
     177             :                           //!< options to the RPC method without nesting them.
     178             :         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
     179             :         AMOUNT,        //!< Special type representing a floating point amount (can be either NUM or STR)
     180             :         STR_HEX,       //!< Special type that is a STR with only hex chars
     181             :         RANGE,         //!< Special type that is a NUM or [NUM,NUM]
     182             :     };
     183             : 
     184             :     enum class Optional {
     185             :         /** Required arg */
     186             :         NO,
     187             :         /**
     188             :          * Optional argument for which the default value is omitted from
     189             :          * help text for one of two reasons:
     190             :          * - It's a named argument and has a default value of `null`.
     191             :          * - Its default value is implicitly clear. That is, elements in an
     192             :          *    array may not exist by default.
     193             :          * When possible, the default value should be specified.
     194             :          */
     195             :         OMITTED,
     196             :     };
     197             :     /** Hint for default value */
     198             :     using DefaultHint = std::string;
     199             :     /** Default constant value */
     200             :     using Default = UniValue;
     201             :     using Fallback = std::variant<Optional, DefaultHint, Default>;
     202             : 
     203             :     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)
     204             :     const Type m_type;
     205             :     const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts
     206             :     const Fallback m_fallback;
     207             :     const std::string m_description;
     208             :     const RPCArgOptions m_opts;
     209             : 
     210         812 :     RPCArg(
     211             :         std::string name,
     212             :         Type type,
     213             :         Fallback fallback,
     214             :         std::string description,
     215             :         RPCArgOptions opts = {})
     216         406 :         : m_names{std::move(name)},
     217         406 :           m_type{std::move(type)},
     218         406 :           m_fallback{std::move(fallback)},
     219         406 :           m_description{std::move(description)},
     220         406 :           m_opts{std::move(opts)}
     221             :     {
     222         406 :         CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ && type != Type::OBJ_NAMED_PARAMS && type != Type::OBJ_USER_KEYS);
     223         406 :     }
     224             : 
     225          74 :     RPCArg(
     226             :         std::string name,
     227             :         Type type,
     228             :         Fallback fallback,
     229             :         std::string description,
     230             :         std::vector<RPCArg> inner,
     231             :         RPCArgOptions opts = {})
     232          74 :         : m_names{std::move(name)},
     233          74 :           m_type{std::move(type)},
     234          74 :           m_inner{std::move(inner)},
     235          74 :           m_fallback{std::move(fallback)},
     236          74 :           m_description{std::move(description)},
     237          74 :           m_opts{std::move(opts)}
     238             :     {
     239          74 :         CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ || type == Type::OBJ_NAMED_PARAMS || type == Type::OBJ_USER_KEYS);
     240          74 :     }
     241             : 
     242             :     bool IsOptional() const;
     243             : 
     244             :     /**
     245             :      * Check whether the request JSON type matches.
     246             :      * Returns true if type matches, or object describing error(s) if not.
     247             :      */
     248             :     UniValue MatchesType(const UniValue& request) const;
     249             : 
     250             :     /** Return the first of all aliases */
     251             :     std::string GetFirstName() const;
     252             : 
     253             :     /** Return the name, throws when there are aliases */
     254             :     std::string GetName() const;
     255             : 
     256             :     /**
     257             :      * Return the type string of the argument.
     258             :      * Set oneline to allow it to be overridden by a custom oneline type string (m_opts.oneline_description).
     259             :      */
     260             :     std::string ToString(bool oneline) const;
     261             :     /**
     262             :      * Return the type string of the argument when it is in an object (dict).
     263             :      * Set oneline to get the oneline representation (less whitespace)
     264             :      */
     265             :     std::string ToStringObj(bool oneline) const;
     266             :     /**
     267             :      * Return the description string, including the argument type and whether
     268             :      * the argument is required.
     269             :      */
     270             :     std::string ToDescriptionString(bool is_named_arg) const;
     271             : };
     272             : 
     273      607754 : struct RPCResult {
     274             :     enum class Type {
     275             :         OBJ,
     276             :         ARR,
     277             :         STR,
     278             :         NUM,
     279             :         BOOL,
     280             :         NONE,
     281             :         ANY,        //!< Special type to disable type checks (for testing only)
     282             :         STR_AMOUNT, //!< Special string to represent a floating point amount
     283             :         STR_HEX,    //!< Special string with only hex chars
     284             :         OBJ_DYN,    //!< Special dictionary with keys that are not literals
     285             :         ARR_FIXED,  //!< Special array that has a fixed number of entries
     286             :         NUM_TIME,   //!< Special numeric to denote unix epoch time
     287             :         ELISION,    //!< Special type to denote elision (...)
     288             :     };
     289             : 
     290             :     const Type m_type;
     291             :     const std::string m_key_name;         //!< Only used for dicts
     292             :     const std::vector<RPCResult> m_inner; //!< Only used for arrays or dicts
     293             :     const bool m_optional;
     294             :     const bool m_skip_type_check;
     295             :     const std::string m_description;
     296             :     const std::string m_cond;
     297             : 
     298          62 :     RPCResult(
     299             :         std::string cond,
     300             :         Type type,
     301             :         std::string m_key_name,
     302             :         bool optional,
     303             :         std::string description,
     304             :         std::vector<RPCResult> inner = {})
     305          62 :         : m_type{std::move(type)},
     306          62 :           m_key_name{std::move(m_key_name)},
     307          62 :           m_inner{std::move(inner)},
     308          62 :           m_optional{optional},
     309          62 :           m_skip_type_check{false},
     310          62 :           m_description{std::move(description)},
     311          62 :           m_cond{std::move(cond)}
     312             :     {
     313          62 :         CHECK_NONFATAL(!m_cond.empty());
     314          62 :         CheckInnerDoc();
     315          62 :     }
     316             : 
     317          62 :     RPCResult(
     318             :         std::string cond,
     319             :         Type type,
     320             :         std::string m_key_name,
     321             :         std::string description,
     322             :         std::vector<RPCResult> inner = {})
     323          62 :         : RPCResult{std::move(cond), type, std::move(m_key_name), /*optional=*/false, std::move(description), std::move(inner)} {}
     324             : 
     325      138783 :     RPCResult(
     326             :         Type type,
     327             :         std::string m_key_name,
     328             :         bool optional,
     329             :         std::string description,
     330             :         std::vector<RPCResult> inner = {},
     331             :         bool skip_type_check = false)
     332      138783 :         : m_type{std::move(type)},
     333      138783 :           m_key_name{std::move(m_key_name)},
     334      138783 :           m_inner{std::move(inner)},
     335      138783 :           m_optional{optional},
     336      138783 :           m_skip_type_check{skip_type_check},
     337      138783 :           m_description{std::move(description)},
     338      138783 :           m_cond{}
     339             :     {
     340      138783 :         CheckInnerDoc();
     341      138783 :     }
     342             : 
     343      102340 :     RPCResult(
     344             :         Type type,
     345             :         std::string m_key_name,
     346             :         std::string description,
     347             :         std::vector<RPCResult> inner = {},
     348             :         bool skip_type_check = false)
     349      102340 :         : RPCResult{type, std::move(m_key_name), /*optional=*/false, std::move(description), std::move(inner), skip_type_check} {}
     350             : 
     351             :     /** Append the sections of the result. */
     352             :     void ToSections(Sections& sections, OuterType outer_type = OuterType::NONE, const int current_indent = 0) const;
     353             :     /** Return the type string of the result when it is in an object (dict). */
     354             :     std::string ToStringObj() const;
     355             :     /** Return the description string, including the result type. */
     356             :     std::string ToDescriptionString() const;
     357             :     /** Check whether the result JSON type matches.
     358             :      * Returns true if type matches, or object describing error(s) if not.
     359             :      */
     360             :     UniValue MatchesType(const UniValue& result) const;
     361             : 
     362             : private:
     363             :     void CheckInnerDoc() const;
     364             : };
     365             : 
     366             : struct RPCResults {
     367             :     const std::vector<RPCResult> m_results;
     368             : 
     369         184 :     RPCResults(RPCResult result)
     370         184 :         : m_results{{result}}
     371             :     {
     372         184 :     }
     373             : 
     374          30 :     RPCResults(std::initializer_list<RPCResult> results)
     375          30 :         : m_results{results}
     376             :     {
     377          30 :     }
     378             : 
     379             :     /**
     380             :      * Return the description string.
     381             :      */
     382             :     std::string ToDescriptionString() const;
     383             : };
     384             : 
     385             : struct RPCExamples {
     386             :     const std::string m_examples;
     387         214 :     explicit RPCExamples(
     388             :         std::string examples)
     389         214 :         : m_examples(std::move(examples))
     390             :     {
     391         214 :     }
     392             :     std::string ToDescriptionString() const;
     393             : };
     394             : 
     395             : class RPCHelpMan
     396             : {
     397             : public:
     398             :     RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples);
     399             :     using RPCMethodImpl = std::function<UniValue(const RPCHelpMan&, const JSONRPCRequest&)>;
     400             :     RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun);
     401             : 
     402             :     UniValue HandleRequest(const JSONRPCRequest& request) const;
     403             :     /**
     404             :      * Helper to get a request argument.
     405             :      * This function only works during m_fun(), i.e. it should only be used in
     406             :      * RPC method implementations. The helper internally checks whether the
     407             :      * user-passed argument isNull() and parses (from JSON) and returns the
     408             :      * user-passed argument, or the default value derived from the RPCArg
     409             :      * documention, or a falsy value if no default was given.
     410             :      *
     411             :      * Use Arg<Type>(i) to get the argument or its default value. Otherwise,
     412             :      * use MaybeArg<Type>(i) to get the optional argument or a falsy value.
     413             :      *
     414             :      * The Type passed to this helper must match the corresponding
     415             :      * RPCArg::Type.
     416             :      */
     417             :     template <typename R>
     418           0 :     auto Arg(size_t i) const
     419             :     {
     420             :         // Return argument (required or with default value).
     421             :         if constexpr (std::is_integral_v<R> || std::is_floating_point_v<R>) {
     422             :             // Return numbers by value.
     423           0 :             return ArgValue<R>(i);
     424             :         } else {
     425             :             // Return everything else by reference.
     426           0 :             return ArgValue<const R&>(i);
     427             :         }
     428             :     }
     429             :     template <typename R>
     430           0 :     auto MaybeArg(size_t i) const
     431             :     {
     432             :         // Return optional argument (without default).
     433             :         if constexpr (std::is_integral_v<R> || std::is_floating_point_v<R>) {
     434             :             // Return numbers by value, wrapped in optional.
     435           0 :             return ArgValue<std::optional<R>>(i);
     436             :         } else {
     437             :             // Return other types by pointer.
     438           0 :             return ArgValue<const R*>(i);
     439             :         }
     440             :     }
     441             :     std::string ToString() const;
     442             :     /** Return the named args that need to be converted from string to another JSON type */
     443             :     UniValue GetArgMap() const;
     444             :     /** If the supplied number of args is neither too small nor too high */
     445             :     bool IsValidNumArgs(size_t num_args) const;
     446             :     //! Return list of arguments and whether they are named-only.
     447             :     std::vector<std::pair<std::string, bool>> GetArgNames() const;
     448             : 
     449             :     const std::string m_name;
     450             : 
     451             : private:
     452             :     const RPCMethodImpl m_fun;
     453             :     const std::string m_description;
     454             :     const std::vector<RPCArg> m_args;
     455             :     const RPCResults m_results;
     456             :     const RPCExamples m_examples;
     457             :     mutable const JSONRPCRequest* m_req{nullptr}; // A pointer to the request for the duration of m_fun()
     458             :     template <typename R>
     459             :     R ArgValue(size_t i) const;
     460             : };
     461             : 
     462             : /**
     463             :  * Push warning messages to an RPC "warnings" field as a JSON array of strings.
     464             :  *
     465             :  * @param[in] warnings  Warning messages to push.
     466             :  * @param[out] obj      UniValue object to push the warnings array object to.
     467             :  */
     468             : void PushWarnings(const UniValue& warnings, UniValue& obj);
     469             : void PushWarnings(const std::vector<bilingual_str>& warnings, UniValue& obj);
     470             : 
     471             : #endif // BITCOIN_RPC_UTIL_H

Generated by: LCOV version 1.14