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 <node/coinstats.h> 9 #include <node/transaction.h> 10 #include <outputtype.h> 11 #include <protocol.h> 12 #include <pubkey.h> 13 #include <rpc/protocol.h> 14 #include <rpc/request.h> 15 #include <script/script.h> 16 #include <script/sign.h> 17 #include <script/standard.h> 18 #include <univalue.h> 19 #include <util/check.h> 20 21 #include <string> 22 #include <vector> 23 24 #include <boost/variant.hpp> 25 26 /** 27 * String used to describe UNIX epoch time in documentation, factored out to a 28 * constant for consistency. 29 */ 30 extern const std::string UNIX_EPOCH_TIME; 31 32 /** 33 * Example bech32 addresses for the RPCExamples help documentation. They are intentionally 34 * invalid to prevent accidental transactions by users. 35 */ 36 extern const std::string EXAMPLE_ADDRESS[2]; 37 38 class FillableSigningProvider; 39 class CPubKey; 40 class CScript; 41 struct Sections; 42 43 /** Wrapper for UniValue::VType, which includes typeAny: 44 * Used to denote don't care type. */ 45 struct UniValueType { UniValueTypeUniValueType46 UniValueType(UniValue::VType _type) : typeAny(false), type(_type) {} UniValueTypeUniValueType47 UniValueType() : typeAny(true) {} 48 bool typeAny; 49 UniValue::VType type; 50 }; 51 52 /** 53 * Type-check arguments; throws JSONRPCError if wrong type given. Does not check that 54 * the right number of arguments are passed, just that any passed are the correct type. 55 */ 56 void RPCTypeCheck(const UniValue& params, 57 const std::list<UniValueType>& typesExpected, bool fAllowNull=false); 58 59 /** 60 * Type-check one argument; throws JSONRPCError if wrong type given. 61 */ 62 void RPCTypeCheckArgument(const UniValue& value, const UniValueType& typeExpected); 63 64 /* 65 Check for expected keys/value types in an Object. 66 */ 67 void RPCTypeCheckObj(const UniValue& o, 68 const std::map<std::string, UniValueType>& typesExpected, 69 bool fAllowNull = false, 70 bool fStrict = false); 71 72 /** 73 * Utilities: convert hex-encoded Values 74 * (throws error if not hex). 75 */ 76 extern uint256 ParseHashV(const UniValue& v, std::string strName); 77 extern uint256 ParseHashO(const UniValue& o, std::string strKey); 78 extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName); 79 extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey); 80 81 CoinStatsHashType ParseHashType(const UniValue& param, const CoinStatsHashType default_type); 82 83 extern CAmount AmountFromValue(const UniValue& value); 84 extern std::string HelpExampleCli(const std::string& methodname, const std::string& args); 85 extern std::string HelpExampleRpc(const std::string& methodname, const std::string& args); 86 87 CPubKey HexToPubKey(const std::string& hex_in); 88 CPubKey AddrToPubKey(const FillableSigningProvider& keystore, const std::string& addr_in); 89 CTxDestination AddAndGetMultisigDestination(const int required, const std::vector<CPubKey>& pubkeys, OutputType type, FillableSigningProvider& keystore, CScript& script_out); 90 91 UniValue DescribeAddress(const CTxDestination& dest); 92 93 //! Parse a confirm target option and raise an RPC error if it is invalid. 94 unsigned int ParseConfirmTarget(const UniValue& value, unsigned int max_target); 95 96 RPCErrorCode RPCErrorFromTransactionError(TransactionError terr); 97 UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_string = ""); 98 99 //! Parse a JSON range specified as int64, or [int64, int64] 100 std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue& value); 101 102 /** Evaluate a descriptor given as a string, or as a {"desc":...,"range":...} object, with default range of 1000. */ 103 std::vector<CScript> EvalDescriptorStringOrObject(const UniValue& scanobject, FlatSigningProvider& provider); 104 105 /** Returns, given services flags, a list of humanly readable (known) network services */ 106 UniValue GetServicesNames(ServiceFlags services); 107 108 /** 109 * Serializing JSON objects depends on the outer type. Only arrays and 110 * dictionaries can be nested in json. The top-level outer type is "NONE". 111 */ 112 enum class OuterType { 113 ARR, 114 OBJ, 115 NONE, // Only set on first recursion 116 }; 117 118 struct RPCArg { 119 enum class Type { 120 OBJ, 121 ARR, 122 STR, 123 NUM, 124 BOOL, 125 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 126 AMOUNT, //!< Special type representing a floating point amount (can be either NUM or STR) 127 STR_HEX, //!< Special type that is a STR with only hex chars 128 RANGE, //!< Special type that is a NUM or [NUM,NUM] 129 }; 130 131 enum class Optional { 132 /** Required arg */ 133 NO, 134 /** 135 * Optional arg that is a named argument and has a default value of 136 * `null`. When possible, the default value should be specified. 137 */ 138 OMITTED_NAMED_ARG, 139 /** 140 * Optional argument with default value omitted because they are 141 * implicitly clear. That is, elements in an array or object may not 142 * exist by default. 143 * When possible, the default value should be specified. 144 */ 145 OMITTED, 146 }; 147 using Fallback = boost::variant<Optional, /* default value for optional args */ std::string>; 148 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) 149 const Type m_type; 150 const bool m_hidden; 151 const std::vector<RPCArg> m_inner; //!< Only used for arrays or dicts 152 const Fallback m_fallback; 153 const std::string m_description; 154 const std::string m_oneline_description; //!< Should be empty unless it is supposed to override the auto-generated summary line 155 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. 156 157 RPCArg( 158 const std::string name, 159 const Type type, 160 const Fallback fallback, 161 const std::string description, 162 const std::string oneline_description = "", 163 const std::vector<std::string> type_str = {}, 164 const bool hidden = false) 165 : m_names{std::move(name)}, 166 m_type{std::move(type)}, 167 m_hidden{hidden}, 168 m_fallback{std::move(fallback)}, 169 m_description{std::move(description)}, 170 m_oneline_description{std::move(oneline_description)}, 171 m_type_str{std::move(type_str)} 172 { 173 CHECK_NONFATAL(type != Type::ARR && type != Type::OBJ); 174 } 175 176 RPCArg( 177 const std::string name, 178 const Type type, 179 const Fallback fallback, 180 const std::string description, 181 const std::vector<RPCArg> inner, 182 const std::string oneline_description = "", 183 const std::vector<std::string> type_str = {}) 184 : m_names{std::move(name)}, 185 m_type{std::move(type)}, 186 m_hidden{false}, 187 m_inner{std::move(inner)}, 188 m_fallback{std::move(fallback)}, 189 m_description{std::move(description)}, 190 m_oneline_description{std::move(oneline_description)}, 191 m_type_str{std::move(type_str)} 192 { 193 CHECK_NONFATAL(type == Type::ARR || type == Type::OBJ); 194 } 195 196 bool IsOptional() const; 197 198 /** Return the first of all aliases */ 199 std::string GetFirstName() const; 200 201 /** Return the name, throws when there are aliases */ 202 std::string GetName() const; 203 204 /** 205 * Return the type string of the argument. 206 * Set oneline to allow it to be overridden by a custom oneline type string (m_oneline_description). 207 */ 208 std::string ToString(bool oneline) const; 209 /** 210 * Return the type string of the argument when it is in an object (dict). 211 * Set oneline to get the oneline representation (less whitespace) 212 */ 213 std::string ToStringObj(bool oneline) const; 214 /** 215 * Return the description string, including the argument type and whether 216 * the argument is required. 217 */ 218 std::string ToDescriptionString() const; 219 }; 220 221 struct RPCResult { 222 enum class Type { 223 OBJ, 224 ARR, 225 STR, 226 NUM, 227 BOOL, 228 NONE, 229 STR_AMOUNT, //!< Special string to represent a floating point amount 230 STR_HEX, //!< Special string with only hex chars 231 OBJ_DYN, //!< Special dictionary with keys that are not literals 232 ARR_FIXED, //!< Special array that has a fixed number of entries 233 NUM_TIME, //!< Special numeric to denote unix epoch time 234 ELISION, //!< Special type to denote elision (...) 235 }; 236 237 const Type m_type; 238 const std::string m_key_name; //!< Only used for dicts 239 const std::vector<RPCResult> m_inner; //!< Only used for arrays or dicts 240 const bool m_optional; 241 const std::string m_description; 242 const std::string m_cond; 243 244 RPCResult( 245 const std::string cond, 246 const Type type, 247 const std::string m_key_name, 248 const bool optional, 249 const std::string description, 250 const std::vector<RPCResult> inner = {}) 251 : m_type{std::move(type)}, 252 m_key_name{std::move(m_key_name)}, 253 m_inner{std::move(inner)}, 254 m_optional{optional}, 255 m_description{std::move(description)}, 256 m_cond{std::move(cond)} 257 { 258 CHECK_NONFATAL(!m_cond.empty()); 259 const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN}; 260 CHECK_NONFATAL(inner_needed != inner.empty()); 261 } 262 263 RPCResult( 264 const std::string cond, 265 const Type type, 266 const std::string m_key_name, 267 const std::string description, 268 const std::vector<RPCResult> inner = {}) 269 : RPCResult{cond, type, m_key_name, false, description, inner} {} 270 271 RPCResult( 272 const Type type, 273 const std::string m_key_name, 274 const bool optional, 275 const std::string description, 276 const std::vector<RPCResult> inner = {}) 277 : m_type{std::move(type)}, 278 m_key_name{std::move(m_key_name)}, 279 m_inner{std::move(inner)}, 280 m_optional{optional}, 281 m_description{std::move(description)}, 282 m_cond{} 283 { 284 const bool inner_needed{type == Type::ARR || type == Type::ARR_FIXED || type == Type::OBJ || type == Type::OBJ_DYN}; 285 CHECK_NONFATAL(inner_needed != inner.empty()); 286 } 287 288 RPCResult( 289 const Type type, 290 const std::string m_key_name, 291 const std::string description, 292 const std::vector<RPCResult> inner = {}) 293 : RPCResult{type, m_key_name, false, description, inner} {} 294 295 /** Append the sections of the result. */ 296 void ToSections(Sections& sections, OuterType outer_type = OuterType::NONE, const int current_indent = 0) const; 297 /** Return the type string of the result when it is in an object (dict). */ 298 std::string ToStringObj() const; 299 /** Return the description string, including the result type. */ 300 std::string ToDescriptionString() const; 301 }; 302 303 struct RPCResults { 304 const std::vector<RPCResult> m_results; 305 RPCResultsRPCResults306 RPCResults(RPCResult result) 307 : m_results{{result}} 308 { 309 } 310 RPCResultsRPCResults311 RPCResults(std::initializer_list<RPCResult> results) 312 : m_results{results} 313 { 314 } 315 316 /** 317 * Return the description string. 318 */ 319 std::string ToDescriptionString() const; 320 }; 321 322 struct RPCExamples { 323 const std::string m_examples; RPCExamplesRPCExamples324 explicit RPCExamples( 325 std::string examples) 326 : m_examples(std::move(examples)) 327 { 328 } 329 std::string ToDescriptionString() const; 330 }; 331 332 class RPCHelpMan 333 { 334 public: 335 RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples); 336 using RPCMethodImpl = std::function<UniValue(const RPCHelpMan&, const JSONRPCRequest&)>; 337 RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples, RPCMethodImpl fun); 338 339 std::string ToString() const; HandleRequest(const JSONRPCRequest & request)340 UniValue HandleRequest(const JSONRPCRequest& request) 341 { 342 Check(request); 343 return m_fun(*this, request); 344 } 345 /** If the supplied number of args is neither too small nor too high */ 346 bool IsValidNumArgs(size_t num_args) const; 347 /** 348 * Check if the given request is valid according to this command or if 349 * the user is asking for help information, and throw help when appropriate. 350 */ Check(const JSONRPCRequest & request)351 inline void Check(const JSONRPCRequest& request) const { 352 if (request.fHelp || !IsValidNumArgs(request.params.size())) { 353 throw std::runtime_error(ToString()); 354 } 355 } 356 357 std::vector<std::string> GetArgNames() const; 358 359 const std::string m_name; 360 361 private: 362 const RPCMethodImpl m_fun; 363 const std::string m_description; 364 const std::vector<RPCArg> m_args; 365 const RPCResults m_results; 366 const RPCExamples m_examples; 367 }; 368 369 #endif // BITCOIN_RPC_UTIL_H 370