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