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