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 #include <key_io.h>
6 #include <keystore.h>
7 #include <policy/fees.h>
8 #include <outputtype.h>
9 #include <rpc/util.h>
10 #include <tinyformat.h>
11 #include <util/strencodings.h>
12 #include <validation.h>
13 
14 InitInterfaces* g_rpc_interfaces = nullptr;
15 
16 // Converts a hex string to a public key if possible
HexToPubKey(const std::string & hex_in)17 CPubKey HexToPubKey(const std::string& hex_in)
18 {
19     if (!IsHex(hex_in)) {
20         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in);
21     }
22     CPubKey vchPubKey(ParseHex(hex_in));
23     if (!vchPubKey.IsFullyValid()) {
24         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid public key: " + hex_in);
25     }
26     return vchPubKey;
27 }
28 
29 // Retrieves a public key for an address from the given CKeyStore
AddrToPubKey(CKeyStore * const keystore,const std::string & addr_in)30 CPubKey AddrToPubKey(CKeyStore* const keystore, const std::string& addr_in)
31 {
32     CTxDestination dest = DecodeDestination(addr_in);
33     if (!IsValidDestination(dest)) {
34         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid address: " + addr_in);
35     }
36     CKeyID key = GetKeyForDestination(*keystore, dest);
37     if (key.IsNull()) {
38         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("%s does not refer to a key", addr_in));
39     }
40     CPubKey vchPubKey;
41     if (!keystore->GetPubKey(key, vchPubKey)) {
42         throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("no full public key for address %s", addr_in));
43     }
44     if (!vchPubKey.IsFullyValid()) {
45        throw JSONRPCError(RPC_INTERNAL_ERROR, "Wallet contains an invalid public key");
46     }
47     return vchPubKey;
48 }
49 
50 // Creates a multisig address from a given list of public keys, number of signatures required, and the address type
AddAndGetMultisigDestination(const int required,const std::vector<CPubKey> & pubkeys,OutputType type,CKeyStore & keystore,CScript & script_out)51 CTxDestination AddAndGetMultisigDestination(const int required, const std::vector<CPubKey>& pubkeys, OutputType type, CKeyStore& keystore, CScript& script_out)
52 {
53     // Gather public keys
54     if (required < 1) {
55         throw JSONRPCError(RPC_INVALID_PARAMETER, "a multisignature address must require at least one key to redeem");
56     }
57     if ((int)pubkeys.size() < required) {
58         throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("not enough keys supplied (got %u keys, but need at least %d to redeem)", pubkeys.size(), required));
59     }
60     if (pubkeys.size() > 16) {
61         throw JSONRPCError(RPC_INVALID_PARAMETER, "Number of keys involved in the multisignature address creation > 16\nReduce the number");
62     }
63 
64     script_out = GetScriptForMultisig(required, pubkeys);
65 
66     if (script_out.size() > MAX_SCRIPT_ELEMENT_SIZE) {
67         throw JSONRPCError(RPC_INVALID_PARAMETER, (strprintf("redeemScript exceeds size limit: %d > %d", script_out.size(), MAX_SCRIPT_ELEMENT_SIZE)));
68     }
69 
70     // Check if any keys are uncompressed. If so, the type is legacy
71     for (const CPubKey& pk : pubkeys) {
72         if (!pk.IsCompressed()) {
73             type = OutputType::LEGACY;
74             break;
75         }
76     }
77 
78     // Make the address
79     CTxDestination dest = AddAndGetDestinationForScript(keystore, script_out, type);
80 
81     return dest;
82 }
83 
84 class DescribeAddressVisitor : public boost::static_visitor<UniValue>
85 {
86 public:
DescribeAddressVisitor()87     explicit DescribeAddressVisitor() {}
88 
operator ()(const CNoDestination & dest) const89     UniValue operator()(const CNoDestination& dest) const
90     {
91         return UniValue(UniValue::VOBJ);
92     }
93 
operator ()(const CKeyID & keyID) const94     UniValue operator()(const CKeyID& keyID) const
95     {
96         UniValue obj(UniValue::VOBJ);
97         obj.pushKV("isscript", false);
98         obj.pushKV("iswitness", false);
99         return obj;
100     }
101 
operator ()(const CScriptID & scriptID) const102     UniValue operator()(const CScriptID& scriptID) const
103     {
104         UniValue obj(UniValue::VOBJ);
105         obj.pushKV("isscript", true);
106         obj.pushKV("iswitness", false);
107         return obj;
108     }
109 
operator ()(const WitnessV0KeyHash & id) const110     UniValue operator()(const WitnessV0KeyHash& id) const
111     {
112         UniValue obj(UniValue::VOBJ);
113         obj.pushKV("isscript", false);
114         obj.pushKV("iswitness", true);
115         obj.pushKV("witness_version", 0);
116         obj.pushKV("witness_program", HexStr(id.begin(), id.end()));
117         return obj;
118     }
119 
operator ()(const WitnessV0ScriptHash & id) const120     UniValue operator()(const WitnessV0ScriptHash& id) const
121     {
122         UniValue obj(UniValue::VOBJ);
123         obj.pushKV("isscript", true);
124         obj.pushKV("iswitness", true);
125         obj.pushKV("witness_version", 0);
126         obj.pushKV("witness_program", HexStr(id.begin(), id.end()));
127         return obj;
128     }
129 
operator ()(const WitnessUnknown & id) const130     UniValue operator()(const WitnessUnknown& id) const
131     {
132         UniValue obj(UniValue::VOBJ);
133         obj.pushKV("iswitness", true);
134         obj.pushKV("witness_version", (int)id.version);
135         obj.pushKV("witness_program", HexStr(id.program, id.program + id.length));
136         return obj;
137     }
138 };
139 
DescribeAddress(const CTxDestination & dest)140 UniValue DescribeAddress(const CTxDestination& dest)
141 {
142     return boost::apply_visitor(DescribeAddressVisitor(), dest);
143 }
144 
ParseConfirmTarget(const UniValue & value)145 unsigned int ParseConfirmTarget(const UniValue& value)
146 {
147     int target = value.get_int();
148     unsigned int max_target = ::feeEstimator.HighestTargetTracked(FeeEstimateHorizon::LONG_HALFLIFE);
149     if (target < 1 || (unsigned int)target > max_target) {
150         throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Invalid conf_target, must be between %u - %u", 1, max_target));
151     }
152     return (unsigned int)target;
153 }
154 
RPCErrorFromTransactionError(TransactionError terr)155 RPCErrorCode RPCErrorFromTransactionError(TransactionError terr)
156 {
157     switch (terr) {
158         case TransactionError::MEMPOOL_REJECTED:
159             return RPC_TRANSACTION_REJECTED;
160         case TransactionError::ALREADY_IN_CHAIN:
161             return RPC_TRANSACTION_ALREADY_IN_CHAIN;
162         case TransactionError::P2P_DISABLED:
163             return RPC_CLIENT_P2P_DISABLED;
164         case TransactionError::INVALID_PSBT:
165         case TransactionError::PSBT_MISMATCH:
166             return RPC_INVALID_PARAMETER;
167         case TransactionError::SIGHASH_MISMATCH:
168             return RPC_DESERIALIZATION_ERROR;
169         default: break;
170     }
171     return RPC_TRANSACTION_ERROR;
172 }
173 
JSONRPCTransactionError(TransactionError terr,const std::string & err_string)174 UniValue JSONRPCTransactionError(TransactionError terr, const std::string& err_string)
175 {
176     if (err_string.length() > 0) {
177         return JSONRPCError(RPCErrorFromTransactionError(terr), err_string);
178     } else {
179         return JSONRPCError(RPCErrorFromTransactionError(terr), TransactionErrorString(terr));
180     }
181 }
182 
183 struct Section {
SectionSection184     Section(const std::string& left, const std::string& right)
185         : m_left{left}, m_right{right} {}
186     const std::string m_left;
187     const std::string m_right;
188 };
189 
190 struct Sections {
191     std::vector<Section> m_sections;
192     size_t m_max_pad{0};
193 
PushSectionSections194     void PushSection(const Section& s)
195     {
196         m_max_pad = std::max(m_max_pad, s.m_left.size());
197         m_sections.push_back(s);
198     }
199 
200     enum class OuterType {
201         ARR,
202         OBJ,
203         NAMED_ARG, // Only set on first recursion
204     };
205 
PushSections206     void Push(const RPCArg& arg, const size_t current_indent = 5, const OuterType outer_type = OuterType::NAMED_ARG)
207     {
208         const auto indent = std::string(current_indent, ' ');
209         const auto indent_next = std::string(current_indent + 2, ' ');
210         switch (arg.m_type) {
211         case RPCArg::Type::STR_HEX:
212         case RPCArg::Type::STR:
213         case RPCArg::Type::NUM:
214         case RPCArg::Type::AMOUNT:
215         case RPCArg::Type::RANGE:
216         case RPCArg::Type::BOOL: {
217             if (outer_type == OuterType::NAMED_ARG) return; // Nothing more to do for non-recursive types on first recursion
218             auto left = indent;
219             if (arg.m_type_str.size() != 0 && outer_type == OuterType::OBJ) {
220                 left += "\"" + arg.m_name + "\": " + arg.m_type_str.at(0);
221             } else {
222                 left += outer_type == OuterType::OBJ ? arg.ToStringObj(/* oneline */ false) : arg.ToString(/* oneline */ false);
223             }
224             left += ",";
225             PushSection({left, arg.ToDescriptionString()});
226             break;
227         }
228         case RPCArg::Type::OBJ:
229         case RPCArg::Type::OBJ_USER_KEYS: {
230             const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString();
231             PushSection({indent + "{", right});
232             for (const auto& arg_inner : arg.m_inner) {
233                 Push(arg_inner, current_indent + 2, OuterType::OBJ);
234             }
235             if (arg.m_type != RPCArg::Type::OBJ) {
236                 PushSection({indent_next + "...", ""});
237             }
238             PushSection({indent + "}" + (outer_type != OuterType::NAMED_ARG ? "," : ""), ""});
239             break;
240         }
241         case RPCArg::Type::ARR: {
242             auto left = indent;
243             left += outer_type == OuterType::OBJ ? "\"" + arg.m_name + "\": " : "";
244             left += "[";
245             const auto right = outer_type == OuterType::NAMED_ARG ? "" : arg.ToDescriptionString();
246             PushSection({left, right});
247             for (const auto& arg_inner : arg.m_inner) {
248                 Push(arg_inner, current_indent + 2, OuterType::ARR);
249             }
250             PushSection({indent_next + "...", ""});
251             PushSection({indent + "]" + (outer_type != OuterType::NAMED_ARG ? "," : ""), ""});
252             break;
253         }
254 
255             // no default case, so the compiler can warn about missing cases
256         }
257     }
258 
ToStringSections259     std::string ToString() const
260     {
261         std::string ret;
262         const size_t pad = m_max_pad + 4;
263         for (const auto& s : m_sections) {
264             if (s.m_right.empty()) {
265                 ret += s.m_left;
266                 ret += "\n";
267                 continue;
268             }
269 
270             std::string left = s.m_left;
271             left.resize(pad, ' ');
272             ret += left;
273 
274             // Properly pad after newlines
275             std::string right;
276             size_t begin = 0;
277             size_t new_line_pos = s.m_right.find_first_of('\n');
278             while (true) {
279                 right += s.m_right.substr(begin, new_line_pos - begin);
280                 if (new_line_pos == std::string::npos) {
281                     break; //No new line
282                 }
283                 right += "\n" + std::string(pad, ' ');
284                 begin = s.m_right.find_first_not_of(' ', new_line_pos + 1);
285                 if (begin == std::string::npos) {
286                     break; // Empty line
287                 }
288                 new_line_pos = s.m_right.find_first_of('\n', begin + 1);
289             }
290             ret += right;
291             ret += "\n";
292         }
293         return ret;
294     }
295 };
296 
RPCHelpMan(std::string name,std::string description,std::vector<RPCArg> args,RPCResults results,RPCExamples examples)297 RPCHelpMan::RPCHelpMan(std::string name, std::string description, std::vector<RPCArg> args, RPCResults results, RPCExamples examples)
298     : m_name{std::move(name)},
299       m_description{std::move(description)},
300       m_args{std::move(args)},
301       m_results{std::move(results)},
302       m_examples{std::move(examples)}
303 {
304     std::set<std::string> named_args;
305     for (const auto& arg : m_args) {
306         // Should have unique named arguments
307         assert(named_args.insert(arg.m_name).second);
308     }
309 }
310 
ToDescriptionString() const311 std::string RPCResults::ToDescriptionString() const
312 {
313     std::string result;
314     for (const auto& r : m_results) {
315         if (r.m_cond.empty()) {
316             result += "\nResult:\n";
317         } else {
318             result += "\nResult (" + r.m_cond + "):\n";
319         }
320         result += r.m_result;
321     }
322     return result;
323 }
324 
ToDescriptionString() const325 std::string RPCExamples::ToDescriptionString() const
326 {
327     return m_examples.empty() ? m_examples : "\nExamples:\n" + m_examples;
328 }
329 
IsValidNumArgs(size_t num_args) const330 bool RPCHelpMan::IsValidNumArgs(size_t num_args) const
331 {
332     size_t num_required_args = 0;
333     for (size_t n = m_args.size(); n > 0; --n) {
334         if (!m_args.at(n - 1).IsOptional()) {
335             num_required_args = n;
336             break;
337         }
338     }
339     return num_required_args <= num_args && num_args <= m_args.size();
340 }
ToString() const341 std::string RPCHelpMan::ToString() const
342 {
343     std::string ret;
344 
345     // Oneline summary
346     ret += m_name;
347     bool was_optional{false};
348     for (const auto& arg : m_args) {
349         const bool optional = arg.IsOptional();
350         ret += " ";
351         if (optional) {
352             if (!was_optional) ret += "( ";
353             was_optional = true;
354         } else {
355             if (was_optional) ret += ") ";
356             was_optional = false;
357         }
358         ret += arg.ToString(/* oneline */ true);
359     }
360     if (was_optional) ret += " )";
361     ret += "\n";
362 
363     // Description
364     ret += m_description;
365 
366     // Arguments
367     Sections sections;
368     for (size_t i{0}; i < m_args.size(); ++i) {
369         const auto& arg = m_args.at(i);
370 
371         if (i == 0) ret += "\nArguments:\n";
372 
373         // Push named argument name and description
374         sections.m_sections.emplace_back(std::to_string(i + 1) + ". " + arg.m_name, arg.ToDescriptionString());
375         sections.m_max_pad = std::max(sections.m_max_pad, sections.m_sections.back().m_left.size());
376 
377         // Recursively push nested args
378         sections.Push(arg);
379     }
380     ret += sections.ToString();
381 
382     // Result
383     ret += m_results.ToDescriptionString();
384 
385     // Examples
386     ret += m_examples.ToDescriptionString();
387 
388     return ret;
389 }
390 
IsOptional() const391 bool RPCArg::IsOptional() const
392 {
393     if (m_fallback.which() == 1) {
394         return true;
395     } else {
396         return RPCArg::Optional::NO != boost::get<RPCArg::Optional>(m_fallback);
397     }
398 }
399 
ToDescriptionString() const400 std::string RPCArg::ToDescriptionString() const
401 {
402     std::string ret;
403     ret += "(";
404     if (m_type_str.size() != 0) {
405         ret += m_type_str.at(1);
406     } else {
407         switch (m_type) {
408         case Type::STR_HEX:
409         case Type::STR: {
410             ret += "string";
411             break;
412         }
413         case Type::NUM: {
414             ret += "numeric";
415             break;
416         }
417         case Type::AMOUNT: {
418             ret += "numeric or string";
419             break;
420         }
421         case Type::RANGE: {
422             ret += "numeric or array";
423             break;
424         }
425         case Type::BOOL: {
426             ret += "boolean";
427             break;
428         }
429         case Type::OBJ:
430         case Type::OBJ_USER_KEYS: {
431             ret += "json object";
432             break;
433         }
434         case Type::ARR: {
435             ret += "json array";
436             break;
437         }
438 
439             // no default case, so the compiler can warn about missing cases
440         }
441     }
442     if (m_fallback.which() == 1) {
443         ret += ", optional, default=" + boost::get<std::string>(m_fallback);
444     } else {
445         switch (boost::get<RPCArg::Optional>(m_fallback)) {
446         case RPCArg::Optional::OMITTED: {
447             // nothing to do. Element is treated as if not present and has no default value
448             break;
449         }
450         case RPCArg::Optional::OMITTED_NAMED_ARG: {
451             ret += ", optional"; // Default value is "null"
452             break;
453         }
454         case RPCArg::Optional::NO: {
455             ret += ", required";
456             break;
457         }
458 
459             // no default case, so the compiler can warn about missing cases
460         }
461     }
462     ret += ")";
463     ret += m_description.empty() ? "" : " " + m_description;
464     return ret;
465 }
466 
ToStringObj(const bool oneline) const467 std::string RPCArg::ToStringObj(const bool oneline) const
468 {
469     std::string res;
470     res += "\"";
471     res += m_name;
472     if (oneline) {
473         res += "\":";
474     } else {
475         res += "\": ";
476     }
477     switch (m_type) {
478     case Type::STR:
479         return res + "\"str\"";
480     case Type::STR_HEX:
481         return res + "\"hex\"";
482     case Type::NUM:
483         return res + "n";
484     case Type::RANGE:
485         return res + "n or [n,n]";
486     case Type::AMOUNT:
487         return res + "amount";
488     case Type::BOOL:
489         return res + "bool";
490     case Type::ARR:
491         res += "[";
492         for (const auto& i : m_inner) {
493             res += i.ToString(oneline) + ",";
494         }
495         return res + "...]";
496     case Type::OBJ:
497     case Type::OBJ_USER_KEYS:
498         // Currently unused, so avoid writing dead code
499         assert(false);
500 
501         // no default case, so the compiler can warn about missing cases
502     }
503     assert(false);
504 }
505 
ToString(const bool oneline) const506 std::string RPCArg::ToString(const bool oneline) const
507 {
508     if (oneline && !m_oneline_description.empty()) return m_oneline_description;
509 
510     switch (m_type) {
511     case Type::STR_HEX:
512     case Type::STR: {
513         return "\"" + m_name + "\"";
514     }
515     case Type::NUM:
516     case Type::RANGE:
517     case Type::AMOUNT:
518     case Type::BOOL: {
519         return m_name;
520     }
521     case Type::OBJ:
522     case Type::OBJ_USER_KEYS: {
523         std::string res;
524         for (size_t i = 0; i < m_inner.size();) {
525             res += m_inner[i].ToStringObj(oneline);
526             if (++i < m_inner.size()) res += ",";
527         }
528         if (m_type == Type::OBJ) {
529             return "{" + res + "}";
530         } else {
531             return "{" + res + ",...}";
532         }
533     }
534     case Type::ARR: {
535         std::string res;
536         for (const auto& i : m_inner) {
537             res += i.ToString(oneline) + ",";
538         }
539         return "[" + res + "...]";
540     }
541 
542         // no default case, so the compiler can warn about missing cases
543     }
544     assert(false);
545 }
546 
ParseRange(const UniValue & value)547 std::pair<int64_t, int64_t> ParseRange(const UniValue& value)
548 {
549     if (value.isNum()) {
550         return {0, value.get_int64()};
551     }
552     if (value.isArray() && value.size() == 2 && value[0].isNum() && value[1].isNum()) {
553         int64_t low = value[0].get_int64();
554         int64_t high = value[1].get_int64();
555         if (low > high) throw JSONRPCError(RPC_INVALID_PARAMETER, "Range specified as [begin,end] must not have begin after end");
556         return {low, high};
557     }
558     throw JSONRPCError(RPC_INVALID_PARAMETER, "Range must be specified as end or as [begin,end]");
559 }
560