Bitcoin ABC  0.28.12
P2P Digital Currency
util.cpp
Go to the documentation of this file.
1 // Copyright (c) 2017-2021 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 <consensus/amount.h>
6 #include <rpc/util.h>
7 
8 #include <key_io.h>
9 #include <script/descriptor.h>
10 #include <script/signingprovider.h>
11 #include <tinyformat.h>
12 #include <util/check.h>
13 #include <util/strencodings.h>
14 #include <util/string.h>
15 #include <util/translation.h>
16 
17 #include <tuple>
18 #include <variant>
19 
20 const std::string UNIX_EPOCH_TIME = "UNIX epoch time";
21 const std::string EXAMPLE_ADDRESS =
22  "\"qrmzys48glkpevp2l4t24jtcltc9hyzx9cep2qffm4\"";
23 
24 void RPCTypeCheck(const UniValue &params,
25  const std::list<UniValueType> &typesExpected,
26  bool fAllowNull) {
27  unsigned int i = 0;
28  for (const UniValueType &t : typesExpected) {
29  if (params.size() <= i) {
30  break;
31  }
32 
33  const UniValue &v = params[i];
34  if (!(fAllowNull && v.isNull())) {
36  }
37  i++;
38  }
39 }
40 
41 void RPCTypeCheckArgument(const UniValue &value,
42  const UniValueType &typeExpected) {
43  if (!typeExpected.typeAny && value.type() != typeExpected.type) {
45  strprintf("Expected type %s, got %s",
46  uvTypeName(typeExpected.type),
47  uvTypeName(value.type())));
48  }
49 }
50 
51 void RPCTypeCheckObj(const UniValue &o,
52  const std::map<std::string, UniValueType> &typesExpected,
53  bool fAllowNull, bool fStrict) {
54  for (const auto &t : typesExpected) {
55  const UniValue &v = o.find_value(t.first);
56  if (!fAllowNull && v.isNull()) {
58  strprintf("Missing %s", t.first));
59  }
60 
61  if (!(t.second.typeAny || v.type() == t.second.type ||
62  (fAllowNull && v.isNull()))) {
63  std::string err = strprintf("Expected type %s for %s, got %s",
64  uvTypeName(t.second.type), t.first,
65  uvTypeName(v.type()));
66  throw JSONRPCError(RPC_TYPE_ERROR, err);
67  }
68  }
69 
70  if (fStrict) {
71  for (const std::string &k : o.getKeys()) {
72  if (typesExpected.count(k) == 0) {
73  std::string err = strprintf("Unexpected key %s", k);
74  throw JSONRPCError(RPC_TYPE_ERROR, err);
75  }
76  }
77  }
78 }
79 
81  if (!value.isNum() && !value.isStr()) {
82  throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
83  }
84 
85  int64_t n;
86  if (!ParseFixedPoint(value.getValStr(), Currency::get().decimals, &n)) {
87  throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
88  }
89 
90  Amount amt = n * SATOSHI;
91  if (!MoneyRange(amt)) {
92  throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
93  }
94 
95  return amt;
96 }
97 
98 uint256 ParseHashV(const UniValue &v, std::string strName) {
99  std::string strHex(v.get_str());
100  if (64 != strHex.length()) {
101  throw JSONRPCError(
103  strprintf("%s must be of length %d (not %d, for '%s')", strName, 64,
104  strHex.length(), strHex));
105  }
106  // Note: IsHex("") is false
107  if (!IsHex(strHex)) {
109  strName + " must be hexadecimal string (not '" +
110  strHex + "')");
111  }
112  return uint256S(strHex);
113 }
114 
115 uint256 ParseHashO(const UniValue &o, std::string strKey) {
116  return ParseHashV(o.find_value(strKey), strKey);
117 }
118 
119 std::vector<uint8_t> ParseHexV(const UniValue &v, std::string strName) {
120  std::string strHex;
121  if (v.isStr()) {
122  strHex = v.get_str();
123  }
124  if (!IsHex(strHex)) {
126  strName + " must be hexadecimal string (not '" +
127  strHex + "')");
128  }
129 
130  return ParseHex(strHex);
131 }
132 
133 std::vector<uint8_t> ParseHexO(const UniValue &o, std::string strKey) {
134  return ParseHexV(o.find_value(strKey), strKey);
135 }
136 
137 namespace {
138 
144 std::string ShellQuote(const std::string &s) {
145  std::string result;
146  result.reserve(s.size() * 2);
147  for (const char ch : s) {
148  if (ch == '\'') {
149  result += "'\''";
150  } else {
151  result += ch;
152  }
153  }
154  return "'" + result + "'";
155 }
156 
163 std::string ShellQuoteIfNeeded(const std::string &s) {
164  for (const char ch : s) {
165  if (ch == ' ' || ch == '\'' || ch == '"') {
166  return ShellQuote(s);
167  }
168  }
169 
170  return s;
171 }
172 
173 } // namespace
174 
175 std::string HelpExampleCli(const std::string &methodname,
176  const std::string &args) {
177  return "> bitcoin-cli " + methodname + " " + args + "\n";
178 }
179 
180 std::string HelpExampleCliNamed(const std::string &methodname,
181  const RPCArgList &args) {
182  std::string result = "> bitcoin-cli -named " + methodname;
183  for (const auto &argpair : args) {
184  const auto &value = argpair.second.isStr() ? argpair.second.get_str()
185  : argpair.second.write();
186  result += " " + argpair.first + "=" + ShellQuoteIfNeeded(value);
187  }
188  result += "\n";
189  return result;
190 }
191 
192 std::string HelpExampleRpc(const std::string &methodname,
193  const std::string &args) {
194  return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", "
195  "\"id\": \"curltest\", "
196  "\"method\": \"" +
197  methodname + "\", \"params\": [" + args +
198  "]}' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
199 }
200 
201 std::string HelpExampleRpcNamed(const std::string &methodname,
202  const RPCArgList &args) {
203  UniValue params(UniValue::VOBJ);
204  for (const auto &param : args) {
205  params.pushKV(param.first, param.second);
206  }
207 
208  return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", "
209  "\"id\": \"curltest\", "
210  "\"method\": \"" +
211  methodname + "\", \"params\": " + params.write() +
212  "}' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
213 }
214 
215 // Converts a hex string to a public key if possible
216 CPubKey HexToPubKey(const std::string &hex_in) {
217  if (!IsHex(hex_in)) {
219  "Invalid public key: " + hex_in);
220  }
221  CPubKey vchPubKey(ParseHex(hex_in));
222  if (!vchPubKey.IsFullyValid()) {
224  "Invalid public key: " + hex_in);
225  }
226  return vchPubKey;
227 }
228 
229 // Retrieves a public key for an address from the given FillableSigningProvider
230 CPubKey AddrToPubKey(const CChainParams &chainparams,
231  const FillableSigningProvider &keystore,
232  const std::string &addr_in) {
233  CTxDestination dest = DecodeDestination(addr_in, chainparams);
234  if (!IsValidDestination(dest)) {
236  "Invalid address: " + addr_in);
237  }
238  CKeyID key = GetKeyForDestination(keystore, dest);
239  if (key.IsNull()) {
241  strprintf("%s does not refer to a key", addr_in));
242  }
243  CPubKey vchPubKey;
244  if (!keystore.GetPubKey(key, vchPubKey)) {
245  throw JSONRPCError(
247  strprintf("no full public key for address %s", addr_in));
248  }
249  if (!vchPubKey.IsFullyValid()) {
251  "Wallet contains an invalid public key");
252  }
253  return vchPubKey;
254 }
255 
256 // Creates a multisig address from a given list of public keys, number of
257 // signatures required, and the address type
259  const std::vector<CPubKey> &pubkeys,
260  OutputType type,
261  FillableSigningProvider &keystore,
262  CScript &script_out) {
263  // Gather public keys
264  if (required < 1) {
265  throw JSONRPCError(
267  "a multisignature address must require at least one key to redeem");
268  }
269  if ((int)pubkeys.size() < required) {
271  strprintf("not enough keys supplied (got %u keys, "
272  "but need at least %d to redeem)",
273  pubkeys.size(), required));
274  }
275  if (pubkeys.size() > 16) {
277  "Number of keys involved in the multisignature "
278  "address creation > 16\nReduce the number");
279  }
280 
281  script_out = GetScriptForMultisig(required, pubkeys);
282 
283  if (script_out.size() > MAX_SCRIPT_ELEMENT_SIZE) {
284  throw JSONRPCError(
286  (strprintf("redeemScript exceeds size limit: %d > %d",
287  script_out.size(), MAX_SCRIPT_ELEMENT_SIZE)));
288  }
289 
290  // Check if any keys are uncompressed. If so, the type is legacy
291  for (const CPubKey &pk : pubkeys) {
292  if (!pk.IsCompressed()) {
293  type = OutputType::LEGACY;
294  break;
295  }
296  }
297 
298  // Make the address
299  CTxDestination dest =
300  AddAndGetDestinationForScript(keystore, script_out, type);
301 
302  return dest;
303 }
304 
306 public:
308 
309  UniValue operator()(const CNoDestination &dest) const {
310  return UniValue(UniValue::VOBJ);
311  }
312 
313  UniValue operator()(const PKHash &keyID) const {
315  obj.pushKV("isscript", false);
316  return obj;
317  }
318 
319  UniValue operator()(const ScriptHash &scriptID) const {
321  obj.pushKV("isscript", true);
322  return obj;
323  }
324 };
325 
327  return std::visit(DescribeAddressVisitor(), dest);
328 }
329 
330 std::string GetAllOutputTypes() {
331  std::vector<std::string> ret;
332  using U = std::underlying_type<TxoutType>::type;
333  for (U i = (U)TxoutType::NONSTANDARD; i <= (U)TxoutType::NULL_DATA; ++i) {
334  ret.emplace_back(GetTxnOutputType(static_cast<TxoutType>(i)));
335  }
336  return Join(ret, ", ");
337 }
338 
340  switch (terr) {
349  return RPC_INVALID_PARAMETER;
352  default:
353  break;
354  }
355  return RPC_TRANSACTION_ERROR;
356 }
357 
359  const std::string &err_string) {
360  if (err_string.length() > 0) {
361  return JSONRPCError(RPCErrorFromTransactionError(terr), err_string);
362  } else {
364  TransactionErrorString(terr).original);
365  }
366 }
367 
372 struct Section {
373  Section(const std::string &left, const std::string &right)
374  : m_left{left}, m_right{right} {}
375  std::string m_left;
376  const std::string m_right;
377 };
378 
383 struct Sections {
384  std::vector<Section> m_sections;
385  size_t m_max_pad{0};
386 
387  void PushSection(const Section &s) {
388  m_max_pad = std::max(m_max_pad, s.m_left.size());
389  m_sections.push_back(s);
390  }
391 
395  void Push(const RPCArg &arg, const size_t current_indent = 5,
396  const OuterType outer_type = OuterType::NONE) {
397  const auto indent = std::string(current_indent, ' ');
398  const auto indent_next = std::string(current_indent + 2, ' ');
399  // Dictionary keys must have a name
400  const bool push_name{outer_type == OuterType::OBJ};
401 
402  switch (arg.m_type) {
404  case RPCArg::Type::STR:
405  case RPCArg::Type::NUM:
407  case RPCArg::Type::RANGE:
408  case RPCArg::Type::BOOL: {
409  // Nothing more to do for non-recursive types on first recursion
410  if (outer_type == OuterType::NONE) {
411  return;
412  }
413  auto left = indent;
414  if (arg.m_type_str.size() != 0 && push_name) {
415  left +=
416  "\"" + arg.GetName() + "\": " + arg.m_type_str.at(0);
417  } else {
418  left += push_name ? arg.ToStringObj(/* oneline */ false)
419  : arg.ToString(/* oneline */ false);
420  }
421  left += ",";
422  PushSection({left, arg.ToDescriptionString()});
423  break;
424  }
425  case RPCArg::Type::OBJ:
427  const auto right = outer_type == OuterType::NONE
428  ? ""
429  : arg.ToDescriptionString();
430  PushSection(
431  {indent + (push_name ? "\"" + arg.GetName() + "\": " : "") +
432  "{",
433  right});
434  for (const auto &arg_inner : arg.m_inner) {
435  Push(arg_inner, current_indent + 2, OuterType::OBJ);
436  }
437  if (arg.m_type != RPCArg::Type::OBJ) {
438  PushSection({indent_next + "...", ""});
439  }
440  PushSection(
441  {indent + "}" + (outer_type != OuterType::NONE ? "," : ""),
442  ""});
443  break;
444  }
445  case RPCArg::Type::ARR: {
446  auto left = indent;
447  left += push_name ? "\"" + arg.GetName() + "\": " : "";
448  left += "[";
449  const auto right = outer_type == OuterType::NONE
450  ? ""
451  : arg.ToDescriptionString();
452  PushSection({left, right});
453  for (const auto &arg_inner : arg.m_inner) {
454  Push(arg_inner, current_indent + 2, OuterType::ARR);
455  }
456  PushSection({indent_next + "...", ""});
457  PushSection(
458  {indent + "]" + (outer_type != OuterType::NONE ? "," : ""),
459  ""});
460  break;
461  } // no default case, so the compiler can warn about missing cases
462  }
463  }
464 
468  std::string ToString() const {
469  std::string ret;
470  const size_t pad = m_max_pad + 4;
471  for (const auto &s : m_sections) {
472  // The left part of a section is assumed to be a single line,
473  // usually it is the name of the JSON struct or a brace like
474  // {, }, [, or ]
475  CHECK_NONFATAL(s.m_left.find('\n') == std::string::npos);
476  if (s.m_right.empty()) {
477  ret += s.m_left;
478  ret += "\n";
479  continue;
480  }
481 
482  std::string left = s.m_left;
483  left.resize(pad, ' ');
484  ret += left;
485 
486  // Properly pad after newlines
487  std::string right;
488  size_t begin = 0;
489  size_t new_line_pos = s.m_right.find_first_of('\n');
490  while (true) {
491  right += s.m_right.substr(begin, new_line_pos - begin);
492  if (new_line_pos == std::string::npos) {
493  // No new line
494  break;
495  }
496  right += "\n" + std::string(pad, ' ');
497  begin = s.m_right.find_first_not_of(' ', new_line_pos + 1);
498  if (begin == std::string::npos) {
499  break; // Empty line
500  }
501  new_line_pos = s.m_right.find_first_of('\n', begin + 1);
502  }
503  ret += right;
504  ret += "\n";
505  }
506  return ret;
507  }
508 };
509 
510 RPCHelpMan::RPCHelpMan(std::string name_, std::string description,
511  std::vector<RPCArg> args, RPCResults results,
512  RPCExamples examples)
513  : RPCHelpMan{std::move(name_), std::move(description), std::move(args),
514  std::move(results), std::move(examples), nullptr} {}
515 
516 RPCHelpMan::RPCHelpMan(std::string name_, std::string description,
517  std::vector<RPCArg> args, RPCResults results,
518  RPCExamples examples, RPCMethodImpl fun)
519  : m_name{std::move(name_)}, m_fun{std::move(fun)},
520  m_description{std::move(description)}, m_args{std::move(args)},
521  m_results{std::move(results)}, m_examples{std::move(examples)} {
522  std::set<std::string> named_args;
523  for (const auto &arg : m_args) {
524  std::vector<std::string> names = SplitString(arg.m_names, '|');
525  // Should have unique named arguments
526  for (const std::string &name : names) {
527  CHECK_NONFATAL(named_args.insert(name).second);
528  }
529  // Default value type should match argument type only when defined
530  if (arg.m_fallback.index() == 2) {
531  const RPCArg::Type type = arg.m_type;
532  switch (std::get<RPCArg::Default>(arg.m_fallback).getType()) {
533  case UniValue::VOBJ:
535  break;
536  case UniValue::VARR:
538  break;
539  case UniValue::VSTR:
541  type == RPCArg::Type::STR_HEX ||
542  type == RPCArg::Type::AMOUNT);
543  break;
544  case UniValue::VNUM:
546  type == RPCArg::Type::AMOUNT ||
547  type == RPCArg::Type::RANGE);
548  break;
549  case UniValue::VBOOL:
551  break;
552  case UniValue::VNULL:
553  // Null values are accepted in all arguments
554  break;
555  default:
556  CHECK_NONFATAL(false);
557  break;
558  }
559  }
560  }
561 }
562 
563 std::string RPCResults::ToDescriptionString() const {
564  std::string result;
565 
566  for (const auto &r : m_results) {
567  if (r.m_type == RPCResult::Type::ANY) {
568  // for testing only
569  continue;
570  }
571  if (r.m_cond.empty()) {
572  result += "\nResult:\n";
573  } else {
574  result += "\nResult (" + r.m_cond + "):\n";
575  }
576  Sections sections;
577  r.ToSections(sections);
578  result += sections.ToString();
579  }
580  return result;
581 }
582 
583 std::string RPCExamples::ToDescriptionString() const {
584  return m_examples.empty() ? m_examples : "\nExamples:\n" + m_examples;
585 }
586 
588  const JSONRPCRequest &request) const {
589  if (request.mode == JSONRPCRequest::GET_ARGS) {
590  return GetArgMap();
591  }
592  /*
593  * Check if the given request is valid according to this command or if
594  * the user is asking for help information, and throw help when appropriate.
595  */
596  if (request.mode == JSONRPCRequest::GET_HELP ||
597  !IsValidNumArgs(request.params.size())) {
598  throw std::runtime_error(ToString());
599  }
600  const UniValue ret = m_fun(*this, config, request);
601  CHECK_NONFATAL(std::any_of(
602  m_results.m_results.begin(), m_results.m_results.end(),
603  [ret](const RPCResult &res) { return res.MatchesType(ret); }));
604  return ret;
605 }
606 
607 bool RPCHelpMan::IsValidNumArgs(size_t num_args) const {
608  size_t num_required_args = 0;
609  for (size_t n = m_args.size(); n > 0; --n) {
610  if (!m_args.at(n - 1).IsOptional()) {
611  num_required_args = n;
612  break;
613  }
614  }
615  return num_required_args <= num_args && num_args <= m_args.size();
616 }
617 
618 std::vector<std::string> RPCHelpMan::GetArgNames() const {
619  std::vector<std::string> ret;
620  for (const auto &arg : m_args) {
621  ret.emplace_back(arg.m_names);
622  }
623  return ret;
624 }
625 
626 std::string RPCHelpMan::ToString() const {
627  std::string ret;
628 
629  // Oneline summary
630  ret += m_name;
631  bool was_optional{false};
632  for (const auto &arg : m_args) {
633  if (arg.m_hidden) {
634  // Any arg that follows is also hidden
635  break;
636  }
637  const bool optional = arg.IsOptional();
638  ret += " ";
639  if (optional) {
640  if (!was_optional) {
641  ret += "( ";
642  }
643  was_optional = true;
644  } else {
645  if (was_optional) {
646  ret += ") ";
647  }
648  was_optional = false;
649  }
650  ret += arg.ToString(/* oneline */ true);
651  }
652  if (was_optional) {
653  ret += " )";
654  }
655  ret += "\n\n";
656 
657  // Description
658  ret += m_description;
659 
660  // Arguments
661  Sections sections;
662  for (size_t i{0}; i < m_args.size(); ++i) {
663  const auto &arg = m_args.at(i);
664  if (arg.m_hidden) {
665  // Any arg that follows is also hidden
666  break;
667  }
668 
669  if (i == 0) {
670  ret += "\nArguments:\n";
671  }
672 
673  // Push named argument name and description
674  sections.m_sections.emplace_back(::ToString(i + 1) + ". " +
675  arg.GetFirstName(),
676  arg.ToDescriptionString());
677  sections.m_max_pad = std::max(sections.m_max_pad,
678  sections.m_sections.back().m_left.size());
679 
680  // Recursively push nested args
681  sections.Push(arg);
682  }
683  ret += sections.ToString();
684 
685  // Result
687 
688  // Examples
690 
691  return ret;
692 }
693 
696  for (int i{0}; i < int(m_args.size()); ++i) {
697  const auto &arg = m_args.at(i);
698  std::vector<std::string> arg_names = SplitString(arg.m_names, '|');
699  for (const auto &arg_name : arg_names) {
701  map.push_back(m_name);
702  map.push_back(i);
703  map.push_back(arg_name);
704  map.push_back(arg.m_type == RPCArg::Type::STR ||
705  arg.m_type == RPCArg::Type::STR_HEX);
706  arr.push_back(map);
707  }
708  }
709  return arr;
710 }
711 
712 std::string RPCArg::GetFirstName() const {
713  return m_names.substr(0, m_names.find("|"));
714 }
715 
716 std::string RPCArg::GetName() const {
717  CHECK_NONFATAL(std::string::npos == m_names.find("|"));
718  return m_names;
719 }
720 
721 bool RPCArg::IsOptional() const {
722  if (m_fallback.index() != 0) {
723  return true;
724  } else {
725  return RPCArg::Optional::NO != std::get<RPCArg::Optional>(m_fallback);
726  }
727 }
728 
729 std::string RPCArg::ToDescriptionString() const {
730  std::string ret;
731  ret += "(";
732  if (m_type_str.size() != 0) {
733  ret += m_type_str.at(1);
734  } else {
735  switch (m_type) {
736  case Type::STR_HEX:
737  case Type::STR: {
738  ret += "string";
739  break;
740  }
741  case Type::NUM: {
742  ret += "numeric";
743  break;
744  }
745  case Type::AMOUNT: {
746  ret += "numeric or string";
747  break;
748  }
749  case Type::RANGE: {
750  ret += "numeric or array";
751  break;
752  }
753  case Type::BOOL: {
754  ret += "boolean";
755  break;
756  }
757  case Type::OBJ:
758  case Type::OBJ_USER_KEYS: {
759  ret += "json object";
760  break;
761  }
762  case Type::ARR: {
763  ret += "json array";
764  break;
765  } // no default case, so the compiler can warn about missing cases
766  }
767  }
768  if (m_fallback.index() == 1) {
769  ret +=
770  ", optional, default=" + std::get<RPCArg::DefaultHint>(m_fallback);
771  } else if (m_fallback.index() == 2) {
772  ret += ", optional, default=" +
773  std::get<RPCArg::Default>(m_fallback).write();
774  } else {
775  switch (std::get<RPCArg::Optional>(m_fallback)) {
777  // nothing to do. Element is treated as if not present and has
778  // no default value
779  break;
780  }
782  ret += ", optional"; // Default value is "null"
783  break;
784  }
785  case RPCArg::Optional::NO: {
786  ret += ", required";
787  break;
788  } // no default case, so the compiler can warn about missing cases
789  }
790  }
791  ret += ")";
792  ret += m_description.empty() ? "" : " " + m_description;
793  return ret;
794 }
795 
796 void RPCResult::ToSections(Sections &sections, const OuterType outer_type,
797  const int current_indent) const {
798  // Indentation
799  const std::string indent(current_indent, ' ');
800  const std::string indent_next(current_indent + 2, ' ');
801 
802  // Elements in a JSON structure (dictionary or array) are separated by a
803  // comma
804  const std::string maybe_separator{outer_type != OuterType::NONE ? "," : ""};
805 
806  // The key name if recursed into an dictionary
807  const std::string maybe_key{
808  outer_type == OuterType::OBJ ? "\"" + this->m_key_name + "\" : " : ""};
809 
810  // Format description with type
811  const auto Description = [&](const std::string &type) {
812  return "(" + type + (this->m_optional ? ", optional" : "") + ")" +
813  (this->m_description.empty() ? "" : " " + this->m_description);
814  };
815 
816  switch (m_type) {
817  case Type::ELISION: {
818  // If the inner result is empty, use three dots for elision
819  sections.PushSection(
820  {indent + "..." + maybe_separator, m_description});
821  return;
822  }
823  case Type::ANY: {
824  // Only for testing
826  }
827  case Type::NONE: {
828  sections.PushSection(
829  {indent + "null" + maybe_separator, Description("json null")});
830  return;
831  }
832  case Type::STR: {
833  sections.PushSection(
834  {indent + maybe_key + "\"str\"" + maybe_separator,
835  Description("string")});
836  return;
837  }
838  case Type::STR_AMOUNT: {
839  sections.PushSection({indent + maybe_key + "n" + maybe_separator,
840  Description("numeric")});
841  return;
842  }
843  case Type::STR_HEX: {
844  sections.PushSection(
845  {indent + maybe_key + "\"hex\"" + maybe_separator,
846  Description("string")});
847  return;
848  }
849  case Type::NUM: {
850  sections.PushSection({indent + maybe_key + "n" + maybe_separator,
851  Description("numeric")});
852  return;
853  }
854  case Type::NUM_TIME: {
855  sections.PushSection({indent + maybe_key + "xxx" + maybe_separator,
856  Description("numeric")});
857  return;
858  }
859  case Type::BOOL: {
860  sections.PushSection(
861  {indent + maybe_key + "true|false" + maybe_separator,
862  Description("boolean")});
863  return;
864  }
865  case Type::ARR_FIXED:
866  case Type::ARR: {
867  sections.PushSection(
868  {indent + maybe_key + "[", Description("json array")});
869  for (const auto &i : m_inner) {
870  i.ToSections(sections, OuterType::ARR, current_indent + 2);
871  }
872  CHECK_NONFATAL(!m_inner.empty());
873  if (m_type == Type::ARR && m_inner.back().m_type != Type::ELISION) {
874  sections.PushSection({indent_next + "...", ""});
875  } else {
876  // Remove final comma, which would be invalid JSON
877  sections.m_sections.back().m_left.pop_back();
878  }
879  sections.PushSection({indent + "]" + maybe_separator, ""});
880  return;
881  }
882  case Type::OBJ_DYN:
883  case Type::OBJ_EMPTY: {
884  sections.PushSection(
885  {indent + maybe_key + "{}", Description("empty JSON object")});
886  return;
887  }
888  case Type::OBJ: {
889  sections.PushSection(
890  {indent + maybe_key + "{", Description("json object")});
891  for (const auto &i : m_inner) {
892  i.ToSections(sections, OuterType::OBJ, current_indent + 2);
893  }
894  CHECK_NONFATAL(!m_inner.empty());
895  if (m_type == Type::OBJ_DYN &&
896  m_inner.back().m_type != Type::ELISION) {
897  // If the dictionary keys are dynamic, use three dots for
898  // continuation
899  sections.PushSection({indent_next + "...", ""});
900  } else {
901  // Remove final comma, which would be invalid JSON
902  sections.m_sections.back().m_left.pop_back();
903  }
904  sections.PushSection({indent + "}" + maybe_separator, ""});
905  return;
906  } // no default case, so the compiler can warn about missing cases
907  }
909 }
910 
911 bool RPCResult::MatchesType(const UniValue &result) const {
912  switch (m_type) {
913  case Type::ELISION: {
914  return false;
915  }
916  case Type::ANY: {
917  return true;
918  }
919  case Type::NONE: {
920  return UniValue::VNULL == result.getType();
921  }
922  case Type::STR:
923  case Type::STR_HEX: {
924  return UniValue::VSTR == result.getType();
925  }
926  case Type::NUM:
927  case Type::STR_AMOUNT:
928  case Type::NUM_TIME: {
929  return UniValue::VNUM == result.getType();
930  }
931  case Type::BOOL: {
932  return UniValue::VBOOL == result.getType();
933  }
934  case Type::ARR_FIXED:
935  case Type::ARR: {
936  return UniValue::VARR == result.getType();
937  }
938  case Type::OBJ_DYN:
939  case Type::OBJ_EMPTY:
940  case Type::OBJ: {
941  return UniValue::VOBJ == result.getType();
942  }
943  } // no default case, so the compiler can warn about missing cases
945 }
946 
947 std::string RPCArg::ToStringObj(const bool oneline) const {
948  std::string res;
949  res += "\"";
950  res += GetFirstName();
951  if (oneline) {
952  res += "\":";
953  } else {
954  res += "\": ";
955  }
956  switch (m_type) {
957  case Type::STR:
958  return res + "\"str\"";
959  case Type::STR_HEX:
960  return res + "\"hex\"";
961  case Type::NUM:
962  return res + "n";
963  case Type::RANGE:
964  return res + "n or [n,n]";
965  case Type::AMOUNT:
966  return res + "amount";
967  case Type::BOOL:
968  return res + "bool";
969  case Type::ARR:
970  res += "[";
971  for (const auto &i : m_inner) {
972  res += i.ToString(oneline) + ",";
973  }
974  return res + "...]";
975  case Type::OBJ:
976  case Type::OBJ_USER_KEYS:
977  // Currently unused, so avoid writing dead code
979 
980  // no default case, so the compiler can warn about missing cases
981  }
983  return res + "unknown";
984 }
985 
986 std::string RPCArg::ToString(const bool oneline) const {
987  if (oneline && !m_oneline_description.empty()) {
988  return m_oneline_description;
989  }
990 
991  switch (m_type) {
992  case Type::STR_HEX:
993  case Type::STR: {
994  return "\"" + GetFirstName() + "\"";
995  }
996  case Type::NUM:
997  case Type::RANGE:
998  case Type::AMOUNT:
999  case Type::BOOL: {
1000  return GetFirstName();
1001  }
1002  case Type::OBJ:
1003  case Type::OBJ_USER_KEYS: {
1004  const std::string res = Join(m_inner, ",", [&](const RPCArg &i) {
1005  return i.ToStringObj(oneline);
1006  });
1007  if (m_type == Type::OBJ) {
1008  return "{" + res + "}";
1009  } else {
1010  return "{" + res + ",...}";
1011  }
1012  }
1013  case Type::ARR: {
1014  std::string res;
1015  for (const auto &i : m_inner) {
1016  res += i.ToString(oneline) + ",";
1017  }
1018  return "[" + res + "...]";
1019  } // no default case, so the compiler can warn about missing cases
1020  }
1022 }
1023 
1024 static std::pair<int64_t, int64_t> ParseRange(const UniValue &value) {
1025  if (value.isNum()) {
1026  return {0, value.get_int64()};
1027  }
1028  if (value.isArray() && value.size() == 2 && value[0].isNum() &&
1029  value[1].isNum()) {
1030  int64_t low = value[0].get_int64();
1031  int64_t high = value[1].get_int64();
1032  if (low > high) {
1033  throw JSONRPCError(
1035  "Range specified as [begin,end] must not have begin after end");
1036  }
1037  return {low, high};
1038  }
1040  "Range must be specified as end or as [begin,end]");
1041 }
1042 
1043 std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue &value) {
1044  int64_t low, high;
1045  std::tie(low, high) = ParseRange(value);
1046  if (low < 0) {
1048  "Range should be greater or equal than 0");
1049  }
1050  if ((high >> 31) != 0) {
1051  throw JSONRPCError(RPC_INVALID_PARAMETER, "End of range is too high");
1052  }
1053  if (high >= low + 1000000) {
1054  throw JSONRPCError(RPC_INVALID_PARAMETER, "Range is too large");
1055  }
1056  return {low, high};
1057 }
1058 
1059 std::vector<CScript>
1061  FlatSigningProvider &provider) {
1062  std::string desc_str;
1063  std::pair<int64_t, int64_t> range = {0, 1000};
1064  if (scanobject.isStr()) {
1065  desc_str = scanobject.get_str();
1066  } else if (scanobject.isObject()) {
1067  const UniValue &desc_uni{scanobject.find_value("desc")};
1068  if (desc_uni.isNull()) {
1069  throw JSONRPCError(
1071  "Descriptor needs to be provided in scan object");
1072  }
1073  desc_str = desc_uni.get_str();
1074  const UniValue &range_uni{scanobject.find_value("range")};
1075  if (!range_uni.isNull()) {
1076  range = ParseDescriptorRange(range_uni);
1077  }
1078  } else {
1079  throw JSONRPCError(
1081  "Scan object needs to be either a string or an object");
1082  }
1083 
1084  std::string error;
1085  auto desc = Parse(desc_str, provider, error);
1086  if (!desc) {
1088  }
1089  if (!desc->IsRange()) {
1090  range.first = 0;
1091  range.second = 0;
1092  }
1093  std::vector<CScript> ret;
1094  for (int i = range.first; i <= range.second; ++i) {
1095  std::vector<CScript> scripts;
1096  if (!desc->Expand(i, provider, scripts, provider)) {
1097  throw JSONRPCError(
1099  strprintf("Cannot derive script without private keys: '%s'",
1100  desc_str));
1101  }
1102  std::move(scripts.begin(), scripts.end(), std::back_inserter(ret));
1103  }
1104  return ret;
1105 }
1106 
1108  UniValue servicesNames(UniValue::VARR);
1109 
1110  for (const auto &flag : serviceFlagsToStr(services)) {
1111  servicesNames.push_back(flag);
1112  }
1113 
1114  return servicesNames;
1115 }
bool MoneyRange(const Amount nValue)
Definition: amount.h:166
static constexpr Amount SATOSHI
Definition: amount.h:143
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:53
#define NONFATAL_UNREACHABLE()
NONFATAL_UNREACHABLE() is a macro that is used to mark unreachable code.
Definition: check.h:106
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:74
A reference to a CKey: the Hash160 of its serialized public key.
Definition: pubkey.h:22
An encapsulated public key.
Definition: pubkey.h:31
bool IsFullyValid() const
fully validate whether this is a valid public key (more expensive than IsValid())
Definition: pubkey.cpp:256
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:431
Definition: config.h:17
UniValue operator()(const CNoDestination &dest) const
Definition: util.cpp:309
UniValue operator()(const ScriptHash &scriptID) const
Definition: util.cpp:319
UniValue operator()(const PKHash &keyID) const
Definition: util.cpp:313
Fillable signing provider that keeps keys in an address->secret map.
virtual bool GetPubKey(const CKeyID &address, CPubKey &vchPubKeyOut) const override
UniValue params
Definition: request.h:34
enum JSONRPCRequest::Mode mode
const RPCExamples m_examples
Definition: util.h:370
std::vector< std::string > GetArgNames() const
Definition: util.cpp:618
RPCHelpMan(std::string name, std::string description, std::vector< RPCArg > args, RPCResults results, RPCExamples examples)
Definition: util.cpp:510
const std::string m_description
Definition: util.h:367
bool IsValidNumArgs(size_t num_args) const
If the supplied number of args is neither too small nor too high.
Definition: util.cpp:607
std::function< UniValue(const RPCHelpMan &, const Config &config, const JSONRPCRequest &)> RPCMethodImpl
Definition: util.h:346
const RPCMethodImpl m_fun
Definition: util.h:366
const std::string m_name
Definition: util.h:363
const RPCResults m_results
Definition: util.h:369
UniValue HandleRequest(const Config &config, const JSONRPCRequest &request) const
Definition: util.cpp:587
const std::vector< RPCArg > m_args
Definition: util.h:368
std::string ToString() const
Definition: util.cpp:626
UniValue GetArgMap() const
Return the named args that need to be converted from string to another JSON type.
Definition: util.cpp:694
const std::string & get_str() const
bool isArray() const
Definition: univalue.h:95
const UniValue & find_value(std::string_view key) const
Definition: univalue.cpp:234
enum VType getType() const
Definition: univalue.h:76
@ VNULL
Definition: univalue.h:27
@ VOBJ
Definition: univalue.h:27
@ VSTR
Definition: univalue.h:27
@ VARR
Definition: univalue.h:27
@ VNUM
Definition: univalue.h:27
@ VBOOL
Definition: univalue.h:27
int64_t get_int64() const
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool isNull() const
Definition: univalue.h:89
const std::string & getValStr() const
Definition: univalue.h:77
size_t size() const
Definition: univalue.h:80
enum VType type() const
Definition: univalue.h:135
const std::vector< std::string > & getKeys() const
bool isStr() const
Definition: univalue.h:93
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
bool isNum() const
Definition: univalue.h:94
bool isObject() const
Definition: univalue.h:96
bool IsNull() const
Definition: uint256.h:30
size_type size() const
Definition: prevector.h:386
256-bit opaque blob.
Definition: uint256.h:127
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
bilingual_str TransactionErrorString(const TransactionError error)
Definition: error.cpp:11
TransactionError
Definition: error.h:22
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:174
Implement std::hash so RCUPtr can be used as a key for maps or sets.
Definition: rcu.h:257
CTxDestination AddAndGetDestinationForScript(FillableSigningProvider &keystore, const CScript &script, OutputType type)
Get a destination of the requested type (if possible) to the specified script.
Definition: outputtype.cpp:49
OutputType
Definition: outputtype.h:16
std::vector< std::string > serviceFlagsToStr(const uint64_t flags)
Convert service flags (a bitmask of NODE_*) to human readable strings.
Definition: protocol.cpp:283
ServiceFlags
nServices flags.
Definition: protocol.h:335
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:57
const char * name
Definition: rest.cpp:48
RPCErrorCode
Bitcoin RPC error codes.
Definition: protocol.h:22
@ RPC_TRANSACTION_ALREADY_IN_CHAIN
Definition: protocol.h:65
@ RPC_TYPE_ERROR
Unexpected type was passed as parameter.
Definition: protocol.h:40
@ RPC_TRANSACTION_REJECTED
Definition: protocol.h:64
@ RPC_TRANSACTION_ERROR
Aliases for backward compatibility.
Definition: protocol.h:63
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:46
@ RPC_INTERNAL_ERROR
Definition: protocol.h:33
@ RPC_DESERIALIZATION_ERROR
Error parsing or validating structure in raw format.
Definition: protocol.h:50
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
@ RPC_CLIENT_P2P_DISABLED
No valid connection manager instance found.
Definition: protocol.h:81
std::pair< int64_t, int64_t > ParseDescriptorRange(const UniValue &value)
Parse a JSON range specified as int64, or [int64, int64].
Definition: util.cpp:1043
std::vector< uint8_t > ParseHexV(const UniValue &v, std::string strName)
Definition: util.cpp:119
void RPCTypeCheck(const UniValue &params, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Definition: util.cpp:24
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:175
UniValue GetServicesNames(ServiceFlags services)
Returns, given services flags, a list of humanly readable (known) network services.
Definition: util.cpp:1107
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FillableSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:258
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:201
void RPCTypeCheckArgument(const UniValue &value, const UniValueType &typeExpected)
Type-check one argument; throws JSONRPCError if wrong type given.
Definition: util.cpp:41
UniValue JSONRPCTransactionError(TransactionError terr, const std::string &err_string)
Definition: util.cpp:358
Amount AmountFromValue(const UniValue &value)
Definition: util.cpp:80
RPCErrorCode RPCErrorFromTransactionError(TransactionError terr)
Definition: util.cpp:339
std::vector< uint8_t > ParseHexO(const UniValue &o, std::string strKey)
Definition: util.cpp:133
const std::string EXAMPLE_ADDRESS
Example CashAddr address used in multiple RPCExamples.
Definition: util.cpp:21
std::vector< CScript > EvalDescriptorStringOrObject(const UniValue &scanobject, FlatSigningProvider &provider)
Evaluate a descriptor given as a string, or as a {"desc":...,"range":...} object, with default range ...
Definition: util.cpp:1060
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:192
const std::string UNIX_EPOCH_TIME
String used to describe UNIX epoch time in documentation, factored out to a constant for consistency.
Definition: util.cpp:20
std::string GetAllOutputTypes()
Definition: util.cpp:330
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:216
CPubKey AddrToPubKey(const CChainParams &chainparams, const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:230
uint256 ParseHashO(const UniValue &o, std::string strKey)
Definition: util.cpp:115
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
Definition: util.cpp:98
void RPCTypeCheckObj(const UniValue &o, const std::map< std::string, UniValueType > &typesExpected, bool fAllowNull, bool fStrict)
Check for expected keys/value types in an Object.
Definition: util.cpp:51
static std::pair< int64_t, int64_t > ParseRange(const UniValue &value)
Definition: util.cpp:1024
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:180
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:326
std::vector< std::pair< std::string, UniValue > > RPCArgList
Definition: util.h:83
OuterType
Serializing JSON objects depends on the outer type.
Definition: util.h:131
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE
Definition: script.h:24
CKeyID GetKeyForDestination(const SigningProvider &store, const CTxDestination &dest)
Return the CKeyID of the key involved in a script (if there is a unique one).
CScript GetScriptForMultisig(int nRequired, const std::vector< CPubKey > &keys)
Generate a multisig script.
Definition: standard.cpp:249
std::string GetTxnOutputType(TxoutType t)
Get the name of a TxoutType as a string.
Definition: standard.cpp:29
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:260
TxoutType
Definition: standard.h:38
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:85
bool ParseFixedPoint(const std::string &val, int decimals, int64_t *amount_out)
Parse number as fixed point according to JSON number syntax.
bool IsHex(const std::string &str)
Returns true if each character in str is a hex character, and has an even number of hex digits.
std::vector< uint8_t > ParseHex(const char *psz)
auto Join(const std::vector< T > &list, const BaseType &separator, UnaryOp unary_op) -> decltype(unary_op(list.at(0)))
Join a list of items.
Definition: string.h:54
std::vector< std::string > SplitString(std::string_view str, char sep)
Definition: string.h:23
Definition: amount.h:19
static const Currency & get()
Definition: amount.cpp:18
uint8_t decimals
Definition: amount.h:149
Definition: util.h:137
Type
Definition: util.h:138
@ RANGE
Special type that is a NUM or [NUM,NUM].
@ OBJ_USER_KEYS
Special type where the user must set the keys e.g.
@ STR_HEX
Special type that is a STR with only hex chars.
@ AMOUNT
Special type representing a floating point amount (can be either NUM or STR)
const std::vector< RPCArg > m_inner
Only used for arrays or dicts.
Definition: util.h:184
const std::string m_names
The name of the arg (can be empty for inner args, can contain multiple aliases separated by | for nam...
Definition: util.h:180
const Fallback m_fallback
Definition: util.h:185
std::string ToString(bool oneline) const
Return the type string of the argument.
Definition: util.cpp:986
const std::string m_description
Definition: util.h:186
bool IsOptional() const
Definition: util.cpp:721
const Type m_type
Definition: util.h:181
const std::vector< std::string > m_type_str
Should be empty unless it is supposed to override the auto-generated type strings.
Definition: util.h:196
std::string GetName() const
Return the name, throws when there are aliases.
Definition: util.cpp:716
std::string GetFirstName() const
Return the first of all aliases.
Definition: util.cpp:712
const std::string m_oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
Definition: util.h:189
std::string ToStringObj(bool oneline) const
Return the type string of the argument when it is in an object (dict).
Definition: util.cpp:947
std::string ToDescriptionString() const
Return the description string, including the argument type and whether the argument is required.
Definition: util.cpp:729
@ OMITTED_NAMED_ARG
Optional arg that is a named argument and has a default value of null.
@ OMITTED
Optional argument with default value omitted because they are implicitly clear.
@ NO
Required arg.
std::string ToDescriptionString() const
Definition: util.cpp:583
const std::string m_examples
Definition: util.h:333
const std::string m_description
Definition: util.h:271
void ToSections(Sections &sections, OuterType outer_type=OuterType::NONE, const int current_indent=0) const
Append the sections of the result.
Definition: util.cpp:796
@ ELISION
Special type to denote elision (...)
@ NUM_TIME
Special numeric to denote unix epoch time.
@ ANY
Special type to disable type checks (for testing only)
@ ARR_FIXED
Special array that has a fixed number of entries.
@ OBJ_DYN
Special dictionary with keys that are not literals.
@ STR_HEX
Special string with only hex chars.
@ STR_AMOUNT
Special string to represent a floating point amount.
@ OBJ_EMPTY
Special type to allow empty OBJ.
const std::vector< RPCResult > m_inner
Only used for arrays or dicts.
Definition: util.h:269
const bool m_optional
Definition: util.h:270
const std::string m_key_name
Only used for dicts.
Definition: util.h:268
bool MatchesType(const UniValue &result) const
Check whether the result JSON type matches.
Definition: util.cpp:911
const Type m_type
Definition: util.h:267
std::string ToDescriptionString() const
Return the description string.
Definition: util.cpp:563
const std::vector< RPCResult > m_results
Definition: util.h:320
A pair of strings that can be aligned (through padding) with other Sections later on.
Definition: util.cpp:372
std::string m_left
Definition: util.cpp:375
Section(const std::string &left, const std::string &right)
Definition: util.cpp:373
const std::string m_right
Definition: util.cpp:376
Keeps track of RPCArgs by transforming them into sections for the purpose of serializing everything t...
Definition: util.cpp:383
void PushSection(const Section &s)
Definition: util.cpp:387
std::vector< Section > m_sections
Definition: util.cpp:384
void Push(const RPCArg &arg, const size_t current_indent=5, const OuterType outer_type=OuterType::NONE)
Recursive helper to translate an RPCArg into sections.
Definition: util.cpp:395
size_t m_max_pad
Definition: util.cpp:385
std::string ToString() const
Concatenate all sections with proper padding.
Definition: util.cpp:468
Wrapper for UniValue::VType, which includes typeAny: used to denote don't care type.
Definition: util.h:44
bool typeAny
Definition: util.h:47
UniValue::VType type
Definition: util.h:48
bool error(const char *fmt, const Args &...args)
Definition: system.h:45
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
uint256 uint256S(const char *str)
uint256 from const char *.
Definition: uint256.h:141
const char * uvTypeName(UniValue::VType t)
Definition: univalue.cpp:219