2022-12-24 23:49:50 +00:00
// Copyright (c) 2017-2022 The Bitcoin Core developers
2017-09-29 00:21:28 -04:00
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
# ifndef BITCOIN_RPC_UTIL_H
# define BITCOIN_RPC_UTIL_H
2023-08-09 05:17:30 -04:00
# include <addresstype.h>
2023-08-07 14:53:42 +02:00
# include <consensus/amount.h>
2019-02-09 20:51:33 -08:00
# include <node/transaction.h>
2019-05-15 00:21:11 -04:00
# include <outputtype.h>
2019-09-23 14:45:51 -04:00
# include <pubkey.h>
2019-02-18 12:11:41 +01:00
# include <rpc/protocol.h>
2019-06-20 02:39:38 +09:00
# include <rpc/request.h>
2019-02-16 15:24:15 -08:00
# include <script/script.h>
# include <script/sign.h>
2023-08-07 14:53:42 +02:00
# include <uint256.h>
2017-12-04 12:49:20 -05:00
# include <univalue.h>
2019-09-23 14:45:51 -04:00
# include <util/check.h>
2017-12-04 12:49:20 -05:00
2023-08-07 14:53:42 +02:00
# include <cstddef>
# include <cstdint>
# include <functional>
# include <initializer_list>
# include <map>
# include <optional>
2017-09-29 00:21:28 -04:00
# include <string>
2023-07-27 12:47:28 -06:00
# include <string_view>
2023-08-07 14:53:42 +02:00
# include <type_traits>
# include <utility>
2021-01-01 15:02:49 +01:00
# include <variant>
2017-09-29 00:21:28 -04:00
# include <vector>
2023-08-07 14:53:42 +02:00
class JSONRPCRequest ;
enum ServiceFlags : uint64_t ;
enum class OutputType ;
enum class TransactionError ;
struct FlatSigningProvider ;
struct bilingual_str ;
2022-05-19 08:03:19 +02:00
static constexpr bool DEFAULT_RPC_DOC_CHECK {
# ifdef RPC_DOC_CHECK
true
# else
false
# endif
} ;
2022-05-17 14:44:20 -07:00
2019-11-26 19:25:56 +01:00
/**
* String used to describe UNIX epoch time in documentation , factored out to a
* constant for consistency .
*/
extern const std : : string UNIX_EPOCH_TIME ;
2020-02-11 23:03:19 +01:00
/**
2020-02-25 19:12:04 +03:00
* Example bech32 addresses for the RPCExamples help documentation . They are intentionally
2020-02-11 23:03:19 +01:00
* invalid to prevent accidental transactions by users .
*/
2020-02-25 19:12:04 +03:00
extern const std : : string EXAMPLE_ADDRESS [ 2 ] ;
2020-02-11 23:03:19 +01:00
2019-06-06 16:33:23 +02:00
class FillableSigningProvider ;
2017-09-29 00:21:28 -04:00
class CScript ;
2020-01-10 00:00:57 +07:00
struct Sections ;
2017-09-29 00:21:28 -04:00
2022-02-14 14:33:39 +01:00
/**
* Gets all existing output types formatted for RPC help sections .
*
* @ return Comma separated string representing output type names .
*/
std : : string GetAllOutputTypes ( ) ;
2019-04-02 16:42:51 -04:00
/** Wrapper for UniValue::VType, which includes typeAny:
* Used to denote don ' t care type . */
struct UniValueType {
UniValueType ( UniValue : : VType _type ) : typeAny ( false ) , type ( _type ) { }
UniValueType ( ) : typeAny ( true ) { }
bool typeAny ;
UniValue : : VType type ;
} ;
/*
Check for expected keys / value types in an Object .
*/
void RPCTypeCheckObj ( const UniValue & o ,
const std : : map < std : : string , UniValueType > & typesExpected ,
bool fAllowNull = false ,
bool fStrict = false ) ;
/**
* Utilities : convert hex - encoded Values
* ( throws error if not hex ) .
*/
2023-07-27 12:47:28 -06:00
uint256 ParseHashV ( const UniValue & v , std : : string_view name ) ;
uint256 ParseHashO ( const UniValue & o , std : : string_view strKey ) ;
std : : vector < unsigned char > ParseHexV ( const UniValue & v , std : : string_view name ) ;
std : : vector < unsigned char > ParseHexO ( const UniValue & o , std : : string_view strKey ) ;
2019-04-02 16:42:51 -04:00
2021-04-27 10:54:44 +02:00
/**
* Validate and return a CAmount from a UniValue number or string .
*
* @ param [ in ] value UniValue number or string to parse .
* @ param [ in ] decimals Number of significant digits ( default : 8 ) .
* @ returns a CAmount if the various checks pass .
*/
2021-05-10 09:13:33 +02:00
CAmount AmountFromValue ( const UniValue & value , int decimals = 8 ) ;
2021-03-03 09:32:14 +01:00
using RPCArgList = std : : vector < std : : pair < std : : string , UniValue > > ;
2021-05-10 09:13:33 +02:00
std : : string HelpExampleCli ( const std : : string & methodname , const std : : string & args ) ;
std : : string HelpExampleCliNamed ( const std : : string & methodname , const RPCArgList & args ) ;
std : : string HelpExampleRpc ( const std : : string & methodname , const std : : string & args ) ;
std : : string HelpExampleRpcNamed ( const std : : string & methodname , const RPCArgList & args ) ;
2019-04-02 16:42:51 -04:00
2017-09-29 00:21:28 -04:00
CPubKey HexToPubKey ( const std : : string & hex_in ) ;
2019-11-24 22:53:42 +01:00
CPubKey AddrToPubKey ( const FillableSigningProvider & keystore , const std : : string & addr_in ) ;
2019-06-06 16:33:23 +02:00
CTxDestination AddAndGetMultisigDestination ( const int required , const std : : vector < CPubKey > & pubkeys , OutputType type , FillableSigningProvider & keystore , CScript & script_out ) ;
2017-09-29 00:21:28 -04:00
2017-12-04 12:49:20 -05:00
UniValue DescribeAddress ( const CTxDestination & dest ) ;
2023-07-21 13:47:43 +02:00
/** Parse a sighash string representation and raise an RPC error if it is invalid. */
int ParseSighashString ( const UniValue & sighash ) ;
2019-02-08 15:29:45 -05:00
//! Parse a confirm target option and raise an RPC error if it is invalid.
2017-07-28 21:40:29 -04:00
unsigned int ParseConfirmTarget ( const UniValue & value , unsigned int max_target ) ;
2019-02-08 15:29:45 -05:00
2019-02-09 20:51:33 -08:00
RPCErrorCode RPCErrorFromTransactionError ( TransactionError terr ) ;
UniValue JSONRPCTransactionError ( TransactionError terr , const std : : string & err_string = " " ) ;
2019-02-27 13:41:41 -08:00
//! Parse a JSON range specified as int64, or [int64, int64]
2019-04-04 00:39:04 -07:00
std : : pair < int64_t , int64_t > ParseDescriptorRange ( const UniValue & value ) ;
2019-02-09 20:51:33 -08:00
2019-02-16 15:24:15 -08:00
/** Evaluate a descriptor given as a string, or as a {"desc":...,"range":...} object, with default range of 1000. */
2022-08-03 19:32:59 -04:00
std : : vector < CScript > EvalDescriptorStringOrObject ( const UniValue & scanobject , FlatSigningProvider & provider , const bool expand_priv = false ) ;
2019-02-16 15:24:15 -08:00
2019-12-26 03:26:59 +07:00
/**
* Serializing JSON objects depends on the outer type . Only arrays and
* dictionaries can be nested in json . The top - level outer type is " NONE " .
*/
enum class OuterType {
ARR ,
OBJ ,
NONE , // Only set on first recursion
} ;
2022-09-13 13:38:37 +02:00
struct RPCArgOptions {
2022-12-12 14:30:14 +01:00
bool skip_type_check { false } ;
2022-09-13 13:38:37 +02:00
std : : string oneline_description { } ; //!< Should be empty unless it is supposed to override the auto-generated summary line
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.
bool hidden { false } ; //!< For testing only
2023-04-19 15:02:38 -04:00
bool also_positional { false } ; //!< If set allows a named-parameter field in an OBJ_NAMED_PARAM options object
//!< to have the same name as a top-level parameter. By default the RPC
//!< framework disallows this, because if an RPC request passes the value by
//!< name, it is assigned to top-level parameter position, not to the options
//!< position, defeating the purpose of using OBJ_NAMED_PARAMS instead OBJ for
//!< that option. But sometimes it makes sense to allow less-commonly used
//!< options to be passed by name only, and more commonly used options to be
//!< passed by name or position, so the RPC framework allows this as long as
//!< methods set the also_positional flag and read values from both positions.
2022-09-13 13:38:37 +02:00
} ;
2018-10-23 15:22:28 -04:00
struct RPCArg {
enum class Type {
OBJ ,
ARR ,
STR ,
NUM ,
BOOL ,
2022-11-10 11:54:11 -05:00
OBJ_NAMED_PARAMS , //!< Special type that behaves almost exactly like
//!< OBJ, defining an options object with a list of
//!< pre-defined keys. The only difference between OBJ
//!< and OBJ_NAMED_PARAMS is that OBJ_NAMED_PARMS
//!< also allows the keys to be passed as top-level
//!< named parameters, as a more convenient way to pass
//!< options to the RPC method without nesting them.
2018-10-23 15:22:28 -04:00
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
AMOUNT , //!< Special type representing a floating point amount (can be either NUM or STR)
STR_HEX , //!< Special type that is a STR with only hex chars
2019-02-27 13:45:47 -08:00
RANGE , //!< Special type that is a NUM or [NUM,NUM]
2018-10-23 15:22:28 -04:00
} ;
2018-12-10 16:56:51 -05:00
enum class Optional {
/** Required arg */
NO ,
/**
2023-01-22 15:05:14 +00:00
* Optional argument for which the default value is omitted from
* help text for one of two reasons :
* - It ' s a named argument and has a default value of ` null ` .
* - Its default value is implicitly clear . That is , elements in an
* array may not exist by default .
2018-12-10 16:56:51 -05:00
* When possible , the default value should be specified .
*/
OMITTED ,
} ;
2023-01-03 13:19:06 +01:00
/** Hint for default value */
2021-04-14 15:01:00 +01:00
using DefaultHint = std : : string ;
2023-01-03 13:19:06 +01:00
/** Default constant value */
2021-04-14 15:01:00 +01:00
using Default = UniValue ;
2023-01-03 13:19:06 +01:00
using Fallback = std : : variant < Optional , DefaultHint , Default > ;
2022-09-13 13:38:37 +02:00
2020-04-12 17:09:23 -04:00
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)
2018-10-23 15:22:28 -04:00
const Type m_type ;
const std : : vector < RPCArg > m_inner ; //!< Only used for arrays or dicts
2018-12-10 16:56:51 -05:00
const Fallback m_fallback ;
2018-11-23 11:21:38 -05:00
const std : : string m_description ;
2022-09-13 13:38:37 +02:00
const RPCArgOptions m_opts ;
2018-11-23 11:21:38 -05:00
RPCArg (
2023-01-03 13:09:32 +01:00
std : : string name ,
Type type ,
Fallback fallback ,
std : : string description ,
2022-09-13 13:38:37 +02:00
RPCArgOptions opts = { } )
2020-04-12 17:09:23 -04:00
: m_names { std : : move ( name ) } ,
2019-12-26 03:26:59 +07:00
m_type { std : : move ( type ) } ,
m_fallback { std : : move ( fallback ) } ,
m_description { std : : move ( description ) } ,
2022-09-13 13:38:37 +02:00
m_opts { std : : move ( opts ) }
2018-10-23 15:22:28 -04:00
{
2022-11-10 11:54:11 -05:00
CHECK_NONFATAL ( type ! = Type : : ARR & & type ! = Type : : OBJ & & type ! = Type : : OBJ_NAMED_PARAMS & & type ! = Type : : OBJ_USER_KEYS ) ;
2018-10-23 15:22:28 -04:00
}
2018-11-23 11:21:38 -05:00
RPCArg (
2023-01-03 13:09:32 +01:00
std : : string name ,
Type type ,
Fallback fallback ,
std : : string description ,
std : : vector < RPCArg > inner ,
2022-09-13 13:38:37 +02:00
RPCArgOptions opts = { } )
2020-04-12 17:09:23 -04:00
: m_names { std : : move ( name ) } ,
2019-12-26 03:26:59 +07:00
m_type { std : : move ( type ) } ,
m_inner { std : : move ( inner ) } ,
m_fallback { std : : move ( fallback ) } ,
m_description { std : : move ( description ) } ,
2022-09-13 13:38:37 +02:00
m_opts { std : : move ( opts ) }
2018-10-23 15:22:28 -04:00
{
2022-11-10 11:54:11 -05:00
CHECK_NONFATAL ( type = = Type : : ARR | | type = = Type : : OBJ | | type = = Type : : OBJ_NAMED_PARAMS | | type = = Type : : OBJ_USER_KEYS ) ;
2018-10-23 15:22:28 -04:00
}
2019-02-12 20:16:29 -05:00
bool IsOptional ( ) const ;
2023-01-20 12:50:25 +01:00
/**
* Check whether the request JSON type matches .
* Returns true if type matches , or object describing error ( s ) if not .
*/
UniValue MatchesType ( const UniValue & request ) const ;
2022-12-12 14:30:14 +01:00
2020-04-12 17:09:23 -04:00
/** Return the first of all aliases */
std : : string GetFirstName ( ) const ;
/** Return the name, throws when there are aliases */
std : : string GetName ( ) const ;
2018-12-04 13:30:06 -05:00
/**
* Return the type string of the argument .
2022-09-13 13:38:37 +02:00
* Set oneline to allow it to be overridden by a custom oneline type string ( m_opts . oneline_description ) .
2018-12-04 13:30:06 -05:00
*/
std : : string ToString ( bool oneline ) const ;
/**
* Return the type string of the argument when it is in an object ( dict ) .
* Set oneline to get the oneline representation ( less whitespace )
*/
std : : string ToStringObj ( bool oneline ) const ;
/**
* Return the description string , including the argument type and whether
* the argument is required .
*/
2023-01-03 13:19:06 +01:00
std : : string ToDescriptionString ( bool is_named_arg ) const ;
2018-10-23 15:22:28 -04:00
} ;
2018-12-21 12:29:36 -05:00
struct RPCResult {
2020-01-10 00:00:57 +07:00
enum class Type {
OBJ ,
ARR ,
STR ,
NUM ,
BOOL ,
NONE ,
2020-11-23 10:41:27 +01:00
ANY , //!< Special type to disable type checks (for testing only)
2020-01-10 00:00:57 +07:00
STR_AMOUNT , //!< Special string to represent a floating point amount
STR_HEX , //!< Special string with only hex chars
OBJ_DYN , //!< Special dictionary with keys that are not literals
ARR_FIXED , //!< Special array that has a fixed number of entries
NUM_TIME , //!< Special numeric to denote unix epoch time
ELISION , //!< Special type to denote elision (...)
} ;
const Type m_type ;
const std : : string m_key_name ; //!< Only used for dicts
const std : : vector < RPCResult > m_inner ; //!< Only used for arrays or dicts
const bool m_optional ;
2021-09-23 20:48:44 +02:00
const bool m_skip_type_check ;
2020-01-10 00:00:57 +07:00
const std : : string m_description ;
2018-12-21 12:29:36 -05:00
const std : : string m_cond ;
2020-01-10 00:00:57 +07:00
RPCResult (
2023-01-03 13:09:32 +01:00
std : : string cond ,
Type type ,
std : : string m_key_name ,
bool optional ,
std : : string description ,
std : : vector < RPCResult > inner = { } )
2020-01-10 00:00:57 +07:00
: m_type { std : : move ( type ) } ,
m_key_name { std : : move ( m_key_name ) } ,
m_inner { std : : move ( inner ) } ,
m_optional { optional } ,
2021-09-23 20:48:44 +02:00
m_skip_type_check { false } ,
2020-01-10 00:00:57 +07:00
m_description { std : : move ( description ) } ,
m_cond { std : : move ( cond ) }
2018-12-21 12:29:36 -05:00
{
2020-01-10 00:00:57 +07:00
CHECK_NONFATAL ( ! m_cond . empty ( ) ) ;
2022-01-25 19:48:26 +01:00
CheckInnerDoc ( ) ;
2018-12-21 12:29:36 -05:00
}
2020-01-10 00:00:57 +07:00
RPCResult (
2023-01-03 13:09:32 +01:00
std : : string cond ,
Type type ,
std : : string m_key_name ,
std : : string description ,
std : : vector < RPCResult > inner = { } )
: RPCResult { std : : move ( cond ) , type , std : : move ( m_key_name ) , /*optional=*/ false , std : : move ( description ) , std : : move ( inner ) } { }
2020-01-10 00:00:57 +07:00
RPCResult (
2023-01-03 13:09:32 +01:00
Type type ,
std : : string m_key_name ,
bool optional ,
std : : string description ,
std : : vector < RPCResult > inner = { } ,
2021-09-23 20:48:44 +02:00
bool skip_type_check = false )
2020-01-10 00:00:57 +07:00
: m_type { std : : move ( type ) } ,
m_key_name { std : : move ( m_key_name ) } ,
m_inner { std : : move ( inner ) } ,
m_optional { optional } ,
2021-09-23 20:48:44 +02:00
m_skip_type_check { skip_type_check } ,
2020-01-10 00:00:57 +07:00
m_description { std : : move ( description ) } ,
m_cond { }
2018-12-21 12:29:36 -05:00
{
2022-01-25 19:48:26 +01:00
CheckInnerDoc ( ) ;
2018-12-21 12:29:36 -05:00
}
2020-01-10 00:00:57 +07:00
RPCResult (
2023-01-03 13:09:32 +01:00
Type type ,
std : : string m_key_name ,
std : : string description ,
std : : vector < RPCResult > inner = { } ,
2021-09-23 20:48:44 +02:00
bool skip_type_check = false )
2023-01-03 13:09:32 +01:00
: RPCResult { type , std : : move ( m_key_name ) , /*optional=*/ false , std : : move ( description ) , std : : move ( inner ) , skip_type_check } { }
2020-01-10 00:00:57 +07:00
/** Append the sections of the result. */
void ToSections ( Sections & sections , OuterType outer_type = OuterType : : NONE , const int current_indent = 0 ) const ;
/** Return the type string of the result when it is in an object (dict). */
std : : string ToStringObj ( ) const ;
/** Return the description string, including the result type. */
std : : string ToDescriptionString ( ) const ;
2023-01-13 20:27:59 +10:00
/** Check whether the result JSON type matches.
* Returns true if type matches , or object describing error ( s ) if not .
*/
UniValue MatchesType ( const UniValue & result ) const ;
2022-01-25 19:48:26 +01:00
private :
void CheckInnerDoc ( ) const ;
2018-12-21 12:29:36 -05:00
} ;
struct RPCResults {
const std : : vector < RPCResult > m_results ;
RPCResults ( RPCResult result )
: m_results { { result } }
{
}
RPCResults ( std : : initializer_list < RPCResult > results )
: m_results { results }
{
}
/**
* Return the description string .
*/
std : : string ToDescriptionString ( ) const ;
} ;
struct RPCExamples {
const std : : string m_examples ;
2018-12-14 14:50:21 +01:00
explicit RPCExamples (
2018-12-21 12:29:36 -05:00
std : : string examples )
: m_examples ( std : : move ( examples ) )
{
}
std : : string ToDescriptionString ( ) const ;
} ;
2018-10-23 15:22:28 -04:00
class RPCHelpMan
{
public :
2018-12-21 12:29:36 -05:00
RPCHelpMan ( std : : string name , std : : string description , std : : vector < RPCArg > args , RPCResults results , RPCExamples examples ) ;
2020-06-26 12:16:22 -04:00
using RPCMethodImpl = std : : function < UniValue ( const RPCHelpMan & , const JSONRPCRequest & ) > ;
RPCHelpMan ( std : : string name , std : : string description , std : : vector < RPCArg > args , RPCResults results , RPCExamples examples , RPCMethodImpl fun ) ;
2018-10-23 15:22:28 -04:00
2020-11-23 10:41:27 +01:00
UniValue HandleRequest ( const JSONRPCRequest & request ) const ;
2023-08-07 14:53:42 +02:00
/**
* Helper to get a request argument .
* This function only works during m_fun ( ) , i . e . it should only be used in
* RPC method implementations . The helper internally checks whether the
* user - passed argument isNull ( ) and parses ( from JSON ) and returns the
* user - passed argument , or the default value derived from the RPCArg
2023-11-07 10:21:51 +09:00
* documentation , or a falsy value if no default was given .
2023-08-07 14:53:42 +02:00
*
* Use Arg < Type > ( i ) to get the argument or its default value . Otherwise ,
* use MaybeArg < Type > ( i ) to get the optional argument or a falsy value .
*
* The Type passed to this helper must match the corresponding
* RPCArg : : Type .
*/
template < typename R >
auto Arg ( size_t i ) const
{
// Return argument (required or with default value).
if constexpr ( std : : is_integral_v < R > | | std : : is_floating_point_v < R > ) {
// Return numbers by value.
return ArgValue < R > ( i ) ;
} else {
// Return everything else by reference.
return ArgValue < const R & > ( i ) ;
}
}
template < typename R >
auto MaybeArg ( size_t i ) const
{
// Return optional argument (without default).
if constexpr ( std : : is_integral_v < R > | | std : : is_floating_point_v < R > ) {
// Return numbers by value, wrapped in optional.
return ArgValue < std : : optional < R > > ( i ) ;
} else {
// Return other types by pointer.
return ArgValue < const R * > ( i ) ;
}
}
2018-10-23 15:22:28 -04:00
std : : string ToString ( ) const ;
2021-01-29 18:15:48 -05:00
/** Return the named args that need to be converted from string to another JSON type */
UniValue GetArgMap ( ) const ;
2019-02-12 20:16:29 -05:00
/** If the supplied number of args is neither too small nor too high */
bool IsValidNumArgs ( size_t num_args ) const ;
2022-11-10 11:54:11 -05:00
//! Return list of arguments and whether they are named-only.
std : : vector < std : : pair < std : : string , bool > > GetArgNames ( ) const ;
2020-06-26 12:16:22 -04:00
2018-10-23 15:22:28 -04:00
const std : : string m_name ;
2020-06-26 12:16:22 -04:00
private :
const RPCMethodImpl m_fun ;
2018-10-20 08:19:44 -04:00
const std : : string m_description ;
2018-10-23 15:22:28 -04:00
const std : : vector < RPCArg > m_args ;
2018-12-21 12:29:36 -05:00
const RPCResults m_results ;
const RPCExamples m_examples ;
2023-08-07 14:53:42 +02:00
mutable const JSONRPCRequest * m_req { nullptr } ; // A pointer to the request for the duration of m_fun()
template < typename R >
R ArgValue ( size_t i ) const ;
2018-10-23 15:22:28 -04:00
} ;
2023-03-19 10:16:09 -07:00
/**
* Push warning messages to an RPC " warnings " field as a JSON array of strings .
*
* @ param [ in ] warnings Warning messages to push .
* @ param [ out ] obj UniValue object to push the warnings array object to .
*/
void PushWarnings ( const UniValue & warnings , UniValue & obj ) ;
2023-03-19 10:19:06 -07:00
void PushWarnings ( const std : : vector < bilingual_str > & warnings , UniValue & obj ) ;
2023-03-19 10:16:09 -07:00
2017-09-29 00:21:28 -04:00
# endif // BITCOIN_RPC_UTIL_H