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