Bitcoin ABC  0.29.9
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 <rpc/util.h>
6 
7 #include <clientversion.h>
8 #include <common/args.h>
9 #include <consensus/amount.h>
10 #include <key_io.h>
11 #include <script/descriptor.h>
12 #include <script/signingprovider.h>
13 #include <tinyformat.h>
14 #include <util/check.h>
15 #include <util/strencodings.h>
16 #include <util/string.h>
17 #include <util/translation.h>
18 
19 #include <tuple>
20 #include <variant>
21 
22 const std::string UNIX_EPOCH_TIME = "UNIX epoch time";
23 const std::string EXAMPLE_ADDRESS =
24  "\"qrmzys48glkpevp2l4t24jtcltc9hyzx9cep2qffm4\"";
25 
26 void RPCTypeCheckObj(const UniValue &o,
27  const std::map<std::string, UniValueType> &typesExpected,
28  bool fAllowNull, bool fStrict) {
29  for (const auto &t : typesExpected) {
30  const UniValue &v = o.find_value(t.first);
31  if (!fAllowNull && v.isNull()) {
33  strprintf("Missing %s", t.first));
34  }
35 
36  if (!(t.second.typeAny || v.type() == t.second.type ||
37  (fAllowNull && v.isNull()))) {
38  std::string err = strprintf("Expected type %s for %s, got %s",
39  uvTypeName(t.second.type), t.first,
40  uvTypeName(v.type()));
41  throw JSONRPCError(RPC_TYPE_ERROR, err);
42  }
43  }
44 
45  if (fStrict) {
46  for (const std::string &k : o.getKeys()) {
47  if (typesExpected.count(k) == 0) {
48  std::string err = strprintf("Unexpected key %s", k);
49  throw JSONRPCError(RPC_TYPE_ERROR, err);
50  }
51  }
52  }
53 }
54 
56  if (!value.isNum() && !value.isStr()) {
57  throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number or string");
58  }
59 
60  int64_t n;
61  if (!ParseFixedPoint(value.getValStr(), Currency::get().decimals, &n)) {
62  throw JSONRPCError(RPC_TYPE_ERROR, "Invalid amount");
63  }
64 
65  Amount amt = n * SATOSHI;
66  if (!MoneyRange(amt)) {
67  throw JSONRPCError(RPC_TYPE_ERROR, "Amount out of range");
68  }
69 
70  return amt;
71 }
72 
73 uint256 ParseHashV(const UniValue &v, std::string strName) {
74  std::string strHex(v.get_str());
75  if (64 != strHex.length()) {
76  throw JSONRPCError(
78  strprintf("%s must be of length %d (not %d, for '%s')", strName, 64,
79  strHex.length(), strHex));
80  }
81  // Note: IsHex("") is false
82  if (!IsHex(strHex)) {
84  strName + " must be hexadecimal string (not '" +
85  strHex + "')");
86  }
87  return uint256S(strHex);
88 }
89 
90 uint256 ParseHashO(const UniValue &o, std::string strKey) {
91  return ParseHashV(o.find_value(strKey), strKey);
92 }
93 
94 std::vector<uint8_t> ParseHexV(const UniValue &v, std::string strName) {
95  std::string strHex;
96  if (v.isStr()) {
97  strHex = v.get_str();
98  }
99  if (!IsHex(strHex)) {
101  strName + " must be hexadecimal string (not '" +
102  strHex + "')");
103  }
104 
105  return ParseHex(strHex);
106 }
107 
108 std::vector<uint8_t> ParseHexO(const UniValue &o, std::string strKey) {
109  return ParseHexV(o.find_value(strKey), strKey);
110 }
111 
112 namespace {
113 
119 std::string ShellQuote(const std::string &s) {
120  std::string result;
121  result.reserve(s.size() * 2);
122  for (const char ch : s) {
123  if (ch == '\'') {
124  result += "'\''";
125  } else {
126  result += ch;
127  }
128  }
129  return "'" + result + "'";
130 }
131 
138 std::string ShellQuoteIfNeeded(const std::string &s) {
139  for (const char ch : s) {
140  if (ch == ' ' || ch == '\'' || ch == '"') {
141  return ShellQuote(s);
142  }
143  }
144 
145  return s;
146 }
147 
148 } // namespace
149 
150 std::string HelpExampleCli(const std::string &methodname,
151  const std::string &args) {
152  return "> bitcoin-cli " + methodname + " " + args + "\n";
153 }
154 
155 std::string HelpExampleCliNamed(const std::string &methodname,
156  const RPCArgList &args) {
157  std::string result = "> bitcoin-cli -named " + methodname;
158  for (const auto &argpair : args) {
159  const auto &value = argpair.second.isStr() ? argpair.second.get_str()
160  : argpair.second.write();
161  result += " " + argpair.first + "=" + ShellQuoteIfNeeded(value);
162  }
163  result += "\n";
164  return result;
165 }
166 
167 std::string HelpExampleRpc(const std::string &methodname,
168  const std::string &args) {
169  return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", "
170  "\"id\": \"curltest\", "
171  "\"method\": \"" +
172  methodname + "\", \"params\": [" + args +
173  "]}' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
174 }
175 
176 std::string HelpExampleRpcNamed(const std::string &methodname,
177  const RPCArgList &args) {
178  UniValue params(UniValue::VOBJ);
179  for (const auto &param : args) {
180  params.pushKV(param.first, param.second);
181  }
182 
183  return "> curl --user myusername --data-binary '{\"jsonrpc\": \"1.0\", "
184  "\"id\": \"curltest\", "
185  "\"method\": \"" +
186  methodname + "\", \"params\": " + params.write() +
187  "}' -H 'content-type: text/plain;' http://127.0.0.1:8332/\n";
188 }
189 
190 // Converts a hex string to a public key if possible
191 CPubKey HexToPubKey(const std::string &hex_in) {
192  if (!IsHex(hex_in)) {
194  "Invalid public key: " + hex_in);
195  }
196  CPubKey vchPubKey(ParseHex(hex_in));
197  if (!vchPubKey.IsFullyValid()) {
199  "Invalid public key: " + hex_in);
200  }
201  return vchPubKey;
202 }
203 
204 // Retrieves a public key for an address from the given FillableSigningProvider
205 CPubKey AddrToPubKey(const CChainParams &chainparams,
206  const FillableSigningProvider &keystore,
207  const std::string &addr_in) {
208  CTxDestination dest = DecodeDestination(addr_in, chainparams);
209  if (!IsValidDestination(dest)) {
211  "Invalid address: " + addr_in);
212  }
213  CKeyID key = GetKeyForDestination(keystore, dest);
214  if (key.IsNull()) {
216  strprintf("%s does not refer to a key", addr_in));
217  }
218  CPubKey vchPubKey;
219  if (!keystore.GetPubKey(key, vchPubKey)) {
220  throw JSONRPCError(
222  strprintf("no full public key for address %s", addr_in));
223  }
224  if (!vchPubKey.IsFullyValid()) {
226  "Wallet contains an invalid public key");
227  }
228  return vchPubKey;
229 }
230 
231 // Creates a multisig address from a given list of public keys, number of
232 // signatures required, and the address type
234  const std::vector<CPubKey> &pubkeys,
235  OutputType type,
236  FillableSigningProvider &keystore,
237  CScript &script_out) {
238  // Gather public keys
239  if (required < 1) {
240  throw JSONRPCError(
242  "a multisignature address must require at least one key to redeem");
243  }
244  if ((int)pubkeys.size() < required) {
246  strprintf("not enough keys supplied (got %u keys, "
247  "but need at least %d to redeem)",
248  pubkeys.size(), required));
249  }
250  if (pubkeys.size() > 16) {
252  "Number of keys involved in the multisignature "
253  "address creation > 16\nReduce the number");
254  }
255 
256  script_out = GetScriptForMultisig(required, pubkeys);
257 
258  if (script_out.size() > MAX_SCRIPT_ELEMENT_SIZE) {
259  throw JSONRPCError(
261  (strprintf("redeemScript exceeds size limit: %d > %d",
262  script_out.size(), MAX_SCRIPT_ELEMENT_SIZE)));
263  }
264 
265  // Check if any keys are uncompressed. If so, the type is legacy
266  for (const CPubKey &pk : pubkeys) {
267  if (!pk.IsCompressed()) {
268  type = OutputType::LEGACY;
269  break;
270  }
271  }
272 
273  // Make the address
274  CTxDestination dest =
275  AddAndGetDestinationForScript(keystore, script_out, type);
276 
277  return dest;
278 }
279 
281 public:
283 
284  UniValue operator()(const CNoDestination &dest) const {
285  return UniValue(UniValue::VOBJ);
286  }
287 
288  UniValue operator()(const PKHash &keyID) const {
290  obj.pushKV("isscript", false);
291  return obj;
292  }
293 
294  UniValue operator()(const ScriptHash &scriptID) const {
296  obj.pushKV("isscript", true);
297  return obj;
298  }
299 };
300 
302  return std::visit(DescribeAddressVisitor(), dest);
303 }
304 
305 std::string GetAllOutputTypes() {
306  std::vector<std::string> ret;
307  using U = std::underlying_type<TxoutType>::type;
308  for (U i = (U)TxoutType::NONSTANDARD; i <= (U)TxoutType::NULL_DATA; ++i) {
309  ret.emplace_back(GetTxnOutputType(static_cast<TxoutType>(i)));
310  }
311  return Join(ret, ", ");
312 }
313 
315  switch (terr) {
324  return RPC_INVALID_PARAMETER;
327  default:
328  break;
329  }
330  return RPC_TRANSACTION_ERROR;
331 }
332 
334  const std::string &err_string) {
335  if (err_string.length() > 0) {
336  return JSONRPCError(RPCErrorFromTransactionError(terr), err_string);
337  } else {
339  TransactionErrorString(terr).original);
340  }
341 }
342 
347 struct Section {
348  Section(const std::string &left, const std::string &right)
349  : m_left{left}, m_right{right} {}
350  std::string m_left;
351  const std::string m_right;
352 };
353 
358 struct Sections {
359  std::vector<Section> m_sections;
360  size_t m_max_pad{0};
361 
362  void PushSection(const Section &s) {
363  m_max_pad = std::max(m_max_pad, s.m_left.size());
364  m_sections.push_back(s);
365  }
366 
370  void Push(const RPCArg &arg, const size_t current_indent = 5,
371  const OuterType outer_type = OuterType::NONE) {
372  const auto indent = std::string(current_indent, ' ');
373  const auto indent_next = std::string(current_indent + 2, ' ');
374  // Dictionary keys must have a name
375  const bool push_name{outer_type == OuterType::OBJ};
376  // True on the first recursion
377  const bool is_top_level_arg{outer_type == OuterType::NONE};
378 
379  switch (arg.m_type) {
381  case RPCArg::Type::STR:
382  case RPCArg::Type::NUM:
384  case RPCArg::Type::RANGE:
385  case RPCArg::Type::BOOL:
387  // Nothing more to do for non-recursive types on first recursion
388  if (is_top_level_arg) {
389  return;
390  }
391  auto left = indent;
392  if (arg.m_opts.type_str.size() != 0 && push_name) {
393  left += "\"" + arg.GetName() +
394  "\": " + arg.m_opts.type_str.at(0);
395  } else {
396  left += push_name ? arg.ToStringObj(/* oneline */ false)
397  : arg.ToString(/* oneline */ false);
398  }
399  left += ",";
400  PushSection({left, arg.ToDescriptionString(
401  /*is_named_arg=*/push_name)});
402  break;
403  }
404  case RPCArg::Type::OBJ:
406  const auto right =
407  is_top_level_arg
408  ? ""
409  : arg.ToDescriptionString(/*is_named_arg=*/push_name);
410  PushSection(
411  {indent + (push_name ? "\"" + arg.GetName() + "\": " : "") +
412  "{",
413  right});
414  for (const auto &arg_inner : arg.m_inner) {
415  Push(arg_inner, current_indent + 2, OuterType::OBJ);
416  }
417  if (arg.m_type != RPCArg::Type::OBJ) {
418  PushSection({indent_next + "...", ""});
419  }
420  PushSection({indent + "}" + (is_top_level_arg ? "" : ","), ""});
421  break;
422  }
423  case RPCArg::Type::ARR: {
424  auto left = indent;
425  left += push_name ? "\"" + arg.GetName() + "\": " : "";
426  left += "[";
427  const auto right =
428  is_top_level_arg
429  ? ""
430  : arg.ToDescriptionString(/*is_named_arg=*/push_name);
431  PushSection({left, right});
432  for (const auto &arg_inner : arg.m_inner) {
433  Push(arg_inner, current_indent + 2, OuterType::ARR);
434  }
435  PushSection({indent_next + "...", ""});
436  PushSection({indent + "]" + (is_top_level_arg ? "" : ","), ""});
437  break;
438  } // no default case, so the compiler can warn about missing cases
439  }
440  }
441 
445  std::string ToString() const {
446  std::string ret;
447  const size_t pad = m_max_pad + 4;
448  for (const auto &s : m_sections) {
449  // The left part of a section is assumed to be a single line,
450  // usually it is the name of the JSON struct or a brace like
451  // {, }, [, or ]
452  CHECK_NONFATAL(s.m_left.find('\n') == std::string::npos);
453  if (s.m_right.empty()) {
454  ret += s.m_left;
455  ret += "\n";
456  continue;
457  }
458 
459  std::string left = s.m_left;
460  left.resize(pad, ' ');
461  ret += left;
462 
463  // Properly pad after newlines
464  std::string right;
465  size_t begin = 0;
466  size_t new_line_pos = s.m_right.find_first_of('\n');
467  while (true) {
468  right += s.m_right.substr(begin, new_line_pos - begin);
469  if (new_line_pos == std::string::npos) {
470  // No new line
471  break;
472  }
473  right += "\n" + std::string(pad, ' ');
474  begin = s.m_right.find_first_not_of(' ', new_line_pos + 1);
475  if (begin == std::string::npos) {
476  break; // Empty line
477  }
478  new_line_pos = s.m_right.find_first_of('\n', begin + 1);
479  }
480  ret += right;
481  ret += "\n";
482  }
483  return ret;
484  }
485 };
486 
487 RPCHelpMan::RPCHelpMan(std::string name_, std::string description,
488  std::vector<RPCArg> args, RPCResults results,
489  RPCExamples examples)
490  : RPCHelpMan{std::move(name_), std::move(description), std::move(args),
491  std::move(results), std::move(examples), nullptr} {}
492 
493 RPCHelpMan::RPCHelpMan(std::string name_, std::string description,
494  std::vector<RPCArg> args, RPCResults results,
495  RPCExamples examples, RPCMethodImpl fun)
496  : m_name{std::move(name_)}, m_fun{std::move(fun)},
497  m_description{std::move(description)}, m_args{std::move(args)},
498  m_results{std::move(results)}, m_examples{std::move(examples)} {
499  // Map of parameter names and types just used to check whether the names are
500  // unique. Parameter names always need to be unique, with the exception that
501  // there can be pairs of POSITIONAL and NAMED parameters with the same name.
502  enum ParamType { POSITIONAL = 1, NAMED = 2, NAMED_ONLY = 4 };
503  std::map<std::string, int> param_names;
504 
505  for (const auto &arg : m_args) {
506  std::vector<std::string> names = SplitString(arg.m_names, '|');
507  // Should have unique named arguments
508  for (const std::string &name : names) {
509  auto &param_type = param_names[name];
510  CHECK_NONFATAL(!(param_type & POSITIONAL));
511  CHECK_NONFATAL(!(param_type & NAMED_ONLY));
512  param_type |= POSITIONAL;
513  }
514  if (arg.m_type == RPCArg::Type::OBJ_NAMED_PARAMS) {
515  for (const auto &inner : arg.m_inner) {
516  std::vector<std::string> inner_names =
517  SplitString(inner.m_names, '|');
518  for (const std::string &inner_name : inner_names) {
519  auto &param_type = param_names[inner_name];
520  CHECK_NONFATAL(!(param_type & POSITIONAL) ||
521  inner.m_opts.also_positional);
522  CHECK_NONFATAL(!(param_type & NAMED));
523  CHECK_NONFATAL(!(param_type & NAMED_ONLY));
524  param_type |=
525  inner.m_opts.also_positional ? NAMED : NAMED_ONLY;
526  }
527  }
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  UniValue arg_mismatch{UniValue::VOBJ};
601  for (size_t i{0}; i < m_args.size(); ++i) {
602  const auto &arg{m_args.at(i)};
603  UniValue match{arg.MatchesType(request.params[i])};
604  if (!match.isTrue()) {
605  arg_mismatch.pushKV(
606  strprintf("Position %s (%s)", i + 1, arg.m_names),
607  std::move(match));
608  }
609  }
610  if (!arg_mismatch.empty()) {
611  throw JSONRPCError(RPC_TYPE_ERROR, strprintf("Wrong type passed:\n%s",
612  arg_mismatch.write(4)));
613  }
614  const UniValue ret = m_fun(*this, config, request);
615  if (gArgs.GetBoolArg("-rpcdoccheck", DEFAULT_RPC_DOC_CHECK)) {
616  UniValue mismatch{UniValue::VARR};
617  for (const auto &res : m_results.m_results) {
618  UniValue match{res.MatchesType(ret)};
619  if (match.isTrue()) {
620  mismatch.setNull();
621  break;
622  }
623  mismatch.push_back(match);
624  }
625  if (!mismatch.isNull()) {
626  std::string explain{mismatch.empty() ? "no possible results defined"
627  : mismatch.size() == 1 ? mismatch[0].write(4)
628  : mismatch.write(4)};
629  throw std::runtime_error{strprintf(
630  "Internal bug detected: RPC call \"%s\" returned incorrect "
631  "type:\n%s\n%s %s\nPlease report this issue here: %s\n",
632  m_name, explain, PACKAGE_NAME, FormatFullVersion(),
633  PACKAGE_BUGREPORT)};
634  }
635  }
636  return ret;
637 }
638 
639 bool RPCHelpMan::IsValidNumArgs(size_t num_args) const {
640  size_t num_required_args = 0;
641  for (size_t n = m_args.size(); n > 0; --n) {
642  if (!m_args.at(n - 1).IsOptional()) {
643  num_required_args = n;
644  break;
645  }
646  }
647  return num_required_args <= num_args && num_args <= m_args.size();
648 }
649 
650 std::vector<std::pair<std::string, bool>> RPCHelpMan::GetArgNames() const {
651  std::vector<std::pair<std::string, bool>> ret;
652  ret.reserve(m_args.size());
653  for (const auto &arg : m_args) {
654  if (arg.m_type == RPCArg::Type::OBJ_NAMED_PARAMS) {
655  for (const auto &inner : arg.m_inner) {
656  ret.emplace_back(inner.m_names, /*named_only=*/true);
657  }
658  }
659  ret.emplace_back(arg.m_names, /*named_only=*/false);
660  }
661  return ret;
662 }
663 
664 std::string RPCHelpMan::ToString() const {
665  std::string ret;
666 
667  // Oneline summary
668  ret += m_name;
669  bool was_optional{false};
670  for (const auto &arg : m_args) {
671  if (arg.m_opts.hidden) {
672  // Any arg that follows is also hidden
673  break;
674  }
675  const bool optional = arg.IsOptional();
676  ret += " ";
677  if (optional) {
678  if (!was_optional) {
679  ret += "( ";
680  }
681  was_optional = true;
682  } else {
683  if (was_optional) {
684  ret += ") ";
685  }
686  was_optional = false;
687  }
688  ret += arg.ToString(/* oneline */ true);
689  }
690  if (was_optional) {
691  ret += " )";
692  }
693  ret += "\n\n";
694 
695  // Description
696  ret += m_description;
697 
698  // Arguments
699  Sections sections;
700  Sections named_only_sections;
701  for (size_t i{0}; i < m_args.size(); ++i) {
702  const auto &arg = m_args.at(i);
703  if (arg.m_opts.hidden) {
704  // Any arg that follows is also hidden
705  break;
706  }
707 
708  // Push named argument name and description
709  sections.m_sections.emplace_back(
710  ::ToString(i + 1) + ". " + arg.GetFirstName(),
711  arg.ToDescriptionString(/*is_named_arg=*/true));
712  sections.m_max_pad = std::max(sections.m_max_pad,
713  sections.m_sections.back().m_left.size());
714 
715  // Recursively push nested args
716  sections.Push(arg);
717 
718  // Push named-only argument sections
719  if (arg.m_type == RPCArg::Type::OBJ_NAMED_PARAMS) {
720  for (const auto &arg_inner : arg.m_inner) {
721  named_only_sections.PushSection(
722  {arg_inner.GetFirstName(),
723  arg_inner.ToDescriptionString(/*is_named_arg=*/true)});
724  named_only_sections.Push(arg_inner);
725  }
726  }
727  }
728 
729  if (!sections.m_sections.empty()) {
730  ret += "\nArguments:\n";
731  }
732  ret += sections.ToString();
733  if (!named_only_sections.m_sections.empty()) {
734  ret += "\nNamed Arguments:\n";
735  }
736  ret += named_only_sections.ToString();
737 
738  // Result
740 
741  // Examples
743 
744  return ret;
745 }
746 
749 
750  auto push_back_arg_info = [&arr](const std::string &rpc_name, int pos,
751  const std::string &arg_name,
752  const RPCArg::Type &type) {
754  map.push_back(rpc_name);
755  map.push_back(pos);
756  map.push_back(arg_name);
757  map.push_back(type == RPCArg::Type::STR ||
758  type == RPCArg::Type::STR_HEX);
759  arr.push_back(map);
760  };
761 
762  for (int i{0}; i < int(m_args.size()); ++i) {
763  const auto &arg = m_args.at(i);
764  std::vector<std::string> arg_names = SplitString(arg.m_names, '|');
765  for (const auto &arg_name : arg_names) {
766  push_back_arg_info(m_name, i, arg_name, arg.m_type);
767  if (arg.m_type == RPCArg::Type::OBJ_NAMED_PARAMS) {
768  for (const auto &inner : arg.m_inner) {
769  std::vector<std::string> inner_names =
770  SplitString(inner.m_names, '|');
771  for (const std::string &inner_name : inner_names) {
772  push_back_arg_info(m_name, i, inner_name, inner.m_type);
773  }
774  }
775  }
776  }
777  }
778  return arr;
779 }
780 
781 static std::optional<UniValue::VType> ExpectedType(RPCArg::Type type) {
782  using Type = RPCArg::Type;
783  switch (type) {
784  case Type::STR_HEX:
785  case Type::STR: {
786  return UniValue::VSTR;
787  }
788  case Type::NUM: {
789  return UniValue::VNUM;
790  }
791  case Type::AMOUNT: {
792  // VNUM or VSTR, checked inside AmountFromValue()
793  return std::nullopt;
794  }
795  case Type::RANGE: {
796  // VNUM or VARR, checked inside ParseRange()
797  return std::nullopt;
798  }
799  case Type::BOOL: {
800  return UniValue::VBOOL;
801  }
802  case Type::OBJ:
803  case Type::OBJ_NAMED_PARAMS:
804  case Type::OBJ_USER_KEYS: {
805  return UniValue::VOBJ;
806  }
807  case Type::ARR: {
808  return UniValue::VARR;
809  }
810  } // no default case, so the compiler can warn about missing cases
812 }
813 
814 UniValue RPCArg::MatchesType(const UniValue &request) const {
815  if (m_opts.skip_type_check) {
816  return true;
817  }
818  if (IsOptional() && request.isNull()) {
819  return true;
820  }
821  const auto exp_type{ExpectedType(m_type)};
822  if (!exp_type) {
823  // nothing to check
824  return true;
825  }
826 
827  if (*exp_type != request.getType()) {
828  return strprintf("JSON value of type %s is not of expected type %s",
829  uvTypeName(request.getType()), uvTypeName(*exp_type));
830  }
831  return true;
832 }
833 
834 std::string RPCArg::GetFirstName() const {
835  return m_names.substr(0, m_names.find("|"));
836 }
837 
838 std::string RPCArg::GetName() const {
839  CHECK_NONFATAL(std::string::npos == m_names.find("|"));
840  return m_names;
841 }
842 
843 bool RPCArg::IsOptional() const {
844  if (m_fallback.index() != 0) {
845  return true;
846  } else {
847  return RPCArg::Optional::NO != std::get<RPCArg::Optional>(m_fallback);
848  }
849 }
850 
851 std::string RPCArg::ToDescriptionString(bool is_named_arg) const {
852  std::string ret;
853  ret += "(";
854  if (m_opts.type_str.size() != 0) {
855  ret += m_opts.type_str.at(1);
856  } else {
857  switch (m_type) {
858  case Type::STR_HEX:
859  case Type::STR: {
860  ret += "string";
861  break;
862  }
863  case Type::NUM: {
864  ret += "numeric";
865  break;
866  }
867  case Type::AMOUNT: {
868  ret += "numeric or string";
869  break;
870  }
871  case Type::RANGE: {
872  ret += "numeric or array";
873  break;
874  }
875  case Type::BOOL: {
876  ret += "boolean";
877  break;
878  }
879  case Type::OBJ:
881  case Type::OBJ_USER_KEYS: {
882  ret += "json object";
883  break;
884  }
885  case Type::ARR: {
886  ret += "json array";
887  break;
888  } // no default case, so the compiler can warn about missing cases
889  }
890  }
891  if (m_fallback.index() == 1) {
892  ret +=
893  ", optional, default=" + std::get<RPCArg::DefaultHint>(m_fallback);
894  } else if (m_fallback.index() == 2) {
895  ret += ", optional, default=" +
896  std::get<RPCArg::Default>(m_fallback).write();
897  } else {
898  switch (std::get<RPCArg::Optional>(m_fallback)) {
899  // Deprecated alias for OMITTED, can be removed
902  // Default value is "null" in dicts. Otherwise, nothing to do.
903  // Element is treated as if not present and has no default value
904  if (is_named_arg) {
905  ret += ", optional";
906  }
907  break;
908  }
909  case RPCArg::Optional::NO: {
910  ret += ", required";
911  break;
912  } // no default case, so the compiler can warn about missing cases
913  }
914  }
915  ret += ")";
917  ret += " Options object that can be used to pass named arguments, "
918  "listed below.";
919  }
920  ret += m_description.empty() ? "" : " " + m_description;
921  return ret;
922 }
923 
924 void RPCResult::ToSections(Sections &sections, const OuterType outer_type,
925  const int current_indent) const {
926  // Indentation
927  const std::string indent(current_indent, ' ');
928  const std::string indent_next(current_indent + 2, ' ');
929 
930  // Elements in a JSON structure (dictionary or array) are separated by a
931  // comma
932  const std::string maybe_separator{outer_type != OuterType::NONE ? "," : ""};
933 
934  // The key name if recursed into a dictionary
935  const std::string maybe_key{
936  outer_type == OuterType::OBJ ? "\"" + this->m_key_name + "\" : " : ""};
937 
938  // Format description with type
939  const auto Description = [&](const std::string &type) {
940  return "(" + type + (this->m_optional ? ", optional" : "") + ")" +
941  (this->m_description.empty() ? "" : " " + this->m_description);
942  };
943 
944  switch (m_type) {
945  case Type::ELISION: {
946  // If the inner result is empty, use three dots for elision
947  sections.PushSection(
948  {indent + "..." + maybe_separator, m_description});
949  return;
950  }
951  case Type::ANY: {
952  // Only for testing
954  }
955  case Type::NONE: {
956  sections.PushSection(
957  {indent + "null" + maybe_separator, Description("json null")});
958  return;
959  }
960  case Type::STR: {
961  sections.PushSection(
962  {indent + maybe_key + "\"str\"" + maybe_separator,
963  Description("string")});
964  return;
965  }
966  case Type::STR_AMOUNT: {
967  sections.PushSection({indent + maybe_key + "n" + maybe_separator,
968  Description("numeric")});
969  return;
970  }
971  case Type::STR_HEX: {
972  sections.PushSection(
973  {indent + maybe_key + "\"hex\"" + maybe_separator,
974  Description("string")});
975  return;
976  }
977  case Type::NUM: {
978  sections.PushSection({indent + maybe_key + "n" + maybe_separator,
979  Description("numeric")});
980  return;
981  }
982  case Type::NUM_TIME: {
983  sections.PushSection({indent + maybe_key + "xxx" + maybe_separator,
984  Description("numeric")});
985  return;
986  }
987  case Type::BOOL: {
988  sections.PushSection(
989  {indent + maybe_key + "true|false" + maybe_separator,
990  Description("boolean")});
991  return;
992  }
993  case Type::ARR_FIXED:
994  case Type::ARR: {
995  sections.PushSection(
996  {indent + maybe_key + "[", Description("json array")});
997  for (const auto &i : m_inner) {
998  i.ToSections(sections, OuterType::ARR, current_indent + 2);
999  }
1000  CHECK_NONFATAL(!m_inner.empty());
1001  if (m_type == Type::ARR && m_inner.back().m_type != Type::ELISION) {
1002  sections.PushSection({indent_next + "...", ""});
1003  } else {
1004  // Remove final comma, which would be invalid JSON
1005  sections.m_sections.back().m_left.pop_back();
1006  }
1007  sections.PushSection({indent + "]" + maybe_separator, ""});
1008  return;
1009  }
1010  case Type::OBJ_DYN:
1011  case Type::OBJ: {
1012  if (m_inner.empty()) {
1013  sections.PushSection({indent + maybe_key + "{}",
1014  Description("empty JSON object")});
1015  return;
1016  }
1017  sections.PushSection(
1018  {indent + maybe_key + "{", Description("json object")});
1019  for (const auto &i : m_inner) {
1020  i.ToSections(sections, OuterType::OBJ, current_indent + 2);
1021  }
1022  if (m_type == Type::OBJ_DYN &&
1023  m_inner.back().m_type != Type::ELISION) {
1024  // If the dictionary keys are dynamic, use three dots for
1025  // continuation
1026  sections.PushSection({indent_next + "...", ""});
1027  } else {
1028  // Remove final comma, which would be invalid JSON
1029  sections.m_sections.back().m_left.pop_back();
1030  }
1031  sections.PushSection({indent + "}" + maybe_separator, ""});
1032  return;
1033  } // no default case, so the compiler can warn about missing cases
1034  }
1036 }
1037 
1038 static std::optional<UniValue::VType> ExpectedType(RPCResult::Type type) {
1039  using Type = RPCResult::Type;
1040  switch (type) {
1041  case Type::ELISION:
1042  case Type::ANY: {
1043  return std::nullopt;
1044  }
1045  case Type::NONE: {
1046  return UniValue::VNULL;
1047  }
1048  case Type::STR:
1049  case Type::STR_HEX: {
1050  return UniValue::VSTR;
1051  }
1052  case Type::NUM:
1053  case Type::STR_AMOUNT:
1054  case Type::NUM_TIME: {
1055  return UniValue::VNUM;
1056  }
1057  case Type::BOOL: {
1058  return UniValue::VBOOL;
1059  }
1060  case Type::ARR_FIXED:
1061  case Type::ARR: {
1062  return UniValue::VARR;
1063  }
1064  case Type::OBJ_DYN:
1065  case Type::OBJ: {
1066  return UniValue::VOBJ;
1067  }
1068  } // no default case, so the compiler can warn about missing cases
1070 }
1071 
1073  if (m_skip_type_check) {
1074  return true;
1075  }
1076 
1077  const auto exp_type = ExpectedType(m_type);
1078  if (!exp_type) {
1079  // can be any type, so nothing to check
1080  return true;
1081  }
1082 
1083  if (*exp_type != result.getType()) {
1084  return strprintf("returned type is %s, but declared as %s in doc",
1085  uvTypeName(result.getType()), uvTypeName(*exp_type));
1086  }
1087 
1088  if (UniValue::VARR == result.getType()) {
1089  UniValue errors(UniValue::VOBJ);
1090  for (size_t i{0}; i < result.get_array().size(); ++i) {
1091  // If there are more results than documented, re-use the last
1092  // doc_inner.
1093  const RPCResult &doc_inner{
1094  m_inner.at(std::min(m_inner.size() - 1, i))};
1095  UniValue match{doc_inner.MatchesType(result.get_array()[i])};
1096  if (!match.isTrue()) {
1097  errors.pushKV(strprintf("%d", i), match);
1098  }
1099  }
1100  if (errors.empty()) {
1101  // empty result array is valid
1102  return true;
1103  }
1104  return errors;
1105  }
1106 
1107  if (UniValue::VOBJ == result.getType()) {
1108  if (!m_inner.empty() && m_inner.at(0).m_type == Type::ELISION) {
1109  return true;
1110  }
1111  UniValue errors(UniValue::VOBJ);
1112  if (m_type == Type::OBJ_DYN) {
1113  // Assume all types are the same, randomly pick the first
1114  const RPCResult &doc_inner{m_inner.at(0)};
1115  for (size_t i{0}; i < result.get_obj().size(); ++i) {
1116  UniValue match{doc_inner.MatchesType(result.get_obj()[i])};
1117  if (!match.isTrue()) {
1118  errors.pushKV(result.getKeys()[i], match);
1119  }
1120  }
1121  if (errors.empty()) {
1122  // empty result obj is valid
1123  return true;
1124  }
1125  return errors;
1126  }
1127  std::set<std::string> doc_keys;
1128  for (const auto &doc_entry : m_inner) {
1129  doc_keys.insert(doc_entry.m_key_name);
1130  }
1131  std::map<std::string, UniValue> result_obj;
1132  result.getObjMap(result_obj);
1133  for (const auto &result_entry : result_obj) {
1134  if (doc_keys.find(result_entry.first) == doc_keys.end()) {
1135  errors.pushKV(result_entry.first,
1136  "key returned that was not in doc");
1137  }
1138  }
1139 
1140  for (const auto &doc_entry : m_inner) {
1141  const auto result_it{result_obj.find(doc_entry.m_key_name)};
1142  if (result_it == result_obj.end()) {
1143  if (!doc_entry.m_optional) {
1144  errors.pushKV(
1145  doc_entry.m_key_name,
1146  "key missing, despite not being optional in doc");
1147  }
1148  continue;
1149  }
1150  UniValue match{doc_entry.MatchesType(result_it->second)};
1151  if (!match.isTrue()) {
1152  errors.pushKV(doc_entry.m_key_name, match);
1153  }
1154  }
1155  if (errors.empty()) {
1156  return true;
1157  }
1158  return errors;
1159  }
1160 
1161  return true;
1162 }
1163 
1165  if (m_type == Type::OBJ) {
1166  // May or may not be empty
1167  return;
1168  }
1169  // Everything else must either be empty or not
1170  const bool inner_needed{m_type == Type::ARR || m_type == Type::ARR_FIXED ||
1171  m_type == Type::OBJ_DYN};
1172  CHECK_NONFATAL(inner_needed != m_inner.empty());
1173 }
1174 
1175 std::string RPCArg::ToStringObj(const bool oneline) const {
1176  std::string res;
1177  res += "\"";
1178  res += GetFirstName();
1179  if (oneline) {
1180  res += "\":";
1181  } else {
1182  res += "\": ";
1183  }
1184  switch (m_type) {
1185  case Type::STR:
1186  return res + "\"str\"";
1187  case Type::STR_HEX:
1188  return res + "\"hex\"";
1189  case Type::NUM:
1190  return res + "n";
1191  case Type::RANGE:
1192  return res + "n or [n,n]";
1193  case Type::AMOUNT:
1194  return res + "amount";
1195  case Type::BOOL:
1196  return res + "bool";
1197  case Type::ARR:
1198  res += "[";
1199  for (const auto &i : m_inner) {
1200  res += i.ToString(oneline) + ",";
1201  }
1202  return res + "...]";
1203  case Type::OBJ:
1205  case Type::OBJ_USER_KEYS:
1206  // Currently unused, so avoid writing dead code
1208 
1209  // no default case, so the compiler can warn about missing cases
1210  }
1212  return res + "unknown";
1213 }
1214 
1215 std::string RPCArg::ToString(const bool oneline) const {
1216  if (oneline && !m_opts.oneline_description.empty()) {
1217  return m_opts.oneline_description;
1218  }
1219 
1220  switch (m_type) {
1221  case Type::STR_HEX:
1222  case Type::STR: {
1223  return "\"" + GetFirstName() + "\"";
1224  }
1225  case Type::NUM:
1226  case Type::RANGE:
1227  case Type::AMOUNT:
1228  case Type::BOOL: {
1229  return GetFirstName();
1230  }
1231  case Type::OBJ:
1233  case Type::OBJ_USER_KEYS: {
1234  const std::string res = Join(m_inner, ",", [&](const RPCArg &i) {
1235  return i.ToStringObj(oneline);
1236  });
1237  if (m_type == Type::OBJ) {
1238  return "{" + res + "}";
1239  } else {
1240  return "{" + res + ",...}";
1241  }
1242  }
1243  case Type::ARR: {
1244  std::string res;
1245  for (const auto &i : m_inner) {
1246  res += i.ToString(oneline) + ",";
1247  }
1248  return "[" + res + "...]";
1249  } // no default case, so the compiler can warn about missing cases
1250  }
1252 }
1253 
1254 static std::pair<int64_t, int64_t> ParseRange(const UniValue &value) {
1255  if (value.isNum()) {
1256  return {0, value.getInt<int64_t>()};
1257  }
1258  if (value.isArray() && value.size() == 2 && value[0].isNum() &&
1259  value[1].isNum()) {
1260  int64_t low = value[0].getInt<int64_t>();
1261  int64_t high = value[1].getInt<int64_t>();
1262  if (low > high) {
1263  throw JSONRPCError(
1265  "Range specified as [begin,end] must not have begin after end");
1266  }
1267  return {low, high};
1268  }
1270  "Range must be specified as end or as [begin,end]");
1271 }
1272 
1273 std::pair<int64_t, int64_t> ParseDescriptorRange(const UniValue &value) {
1274  int64_t low, high;
1275  std::tie(low, high) = ParseRange(value);
1276  if (low < 0) {
1278  "Range should be greater or equal than 0");
1279  }
1280  if ((high >> 31) != 0) {
1281  throw JSONRPCError(RPC_INVALID_PARAMETER, "End of range is too high");
1282  }
1283  if (high >= low + 1000000) {
1284  throw JSONRPCError(RPC_INVALID_PARAMETER, "Range is too large");
1285  }
1286  return {low, high};
1287 }
1288 
1289 std::vector<CScript>
1291  FlatSigningProvider &provider) {
1292  std::string desc_str;
1293  std::pair<int64_t, int64_t> range = {0, 1000};
1294  if (scanobject.isStr()) {
1295  desc_str = scanobject.get_str();
1296  } else if (scanobject.isObject()) {
1297  const UniValue &desc_uni{scanobject.find_value("desc")};
1298  if (desc_uni.isNull()) {
1299  throw JSONRPCError(
1301  "Descriptor needs to be provided in scan object");
1302  }
1303  desc_str = desc_uni.get_str();
1304  const UniValue &range_uni{scanobject.find_value("range")};
1305  if (!range_uni.isNull()) {
1306  range = ParseDescriptorRange(range_uni);
1307  }
1308  } else {
1309  throw JSONRPCError(
1311  "Scan object needs to be either a string or an object");
1312  }
1313 
1314  std::string error;
1315  auto desc = Parse(desc_str, provider, error);
1316  if (!desc) {
1318  }
1319  if (!desc->IsRange()) {
1320  range.first = 0;
1321  range.second = 0;
1322  }
1323  std::vector<CScript> ret;
1324  for (int i = range.first; i <= range.second; ++i) {
1325  std::vector<CScript> scripts;
1326  if (!desc->Expand(i, provider, scripts, provider)) {
1327  throw JSONRPCError(
1329  strprintf("Cannot derive script without private keys: '%s'",
1330  desc_str));
1331  }
1332  std::move(scripts.begin(), scripts.end(), std::back_inserter(ret));
1333  }
1334  return ret;
1335 }
1336 
1338  UniValue servicesNames(UniValue::VARR);
1339 
1340  for (const auto &flag : serviceFlagsToStr(services)) {
1341  servicesNames.push_back(flag);
1342  }
1343 
1344  return servicesNames;
1345 }
bool MoneyRange(const Amount nValue)
Definition: amount.h:166
static constexpr Amount SATOSHI
Definition: amount.h:143
ArgsManager gArgs
Definition: args.cpp:38
#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
bool GetBoolArg(const std::string &strArg, bool fDefault) const
Return boolean argument or default value.
Definition: args.cpp:556
CChainParams defines various tweakable parameters of a given instance of the Bitcoin system.
Definition: chainparams.h:80
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:19
UniValue operator()(const CNoDestination &dest) const
Definition: util.cpp:284
UniValue operator()(const ScriptHash &scriptID) const
Definition: util.cpp:294
UniValue operator()(const PKHash &keyID) const
Definition: util.cpp:288
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:392
RPCHelpMan(std::string name, std::string description, std::vector< RPCArg > args, RPCResults results, RPCExamples examples)
Definition: util.cpp:487
const std::string m_description
Definition: util.h:389
bool IsValidNumArgs(size_t num_args) const
If the supplied number of args is neither too small nor too high.
Definition: util.cpp:639
std::function< UniValue(const RPCHelpMan &, const Config &config, const JSONRPCRequest &)> RPCMethodImpl
Definition: util.h:367
const RPCMethodImpl m_fun
Definition: util.h:388
const std::string m_name
Definition: util.h:385
const RPCResults m_results
Definition: util.h:391
UniValue HandleRequest(const Config &config, const JSONRPCRequest &request) const
Definition: util.cpp:587
const std::vector< RPCArg > m_args
Definition: util.h:390
std::string ToString() const
Definition: util.cpp:664
UniValue GetArgMap() const
Return the named args that need to be converted from string to another JSON type.
Definition: util.cpp:747
std::vector< std::pair< std::string, bool > > GetArgNames() const
Return list of arguments and whether they are named-only.
Definition: util.cpp:650
void push_back(UniValue val)
Definition: univalue.cpp:96
const std::string & get_str() const
bool isArray() const
Definition: univalue.h:110
const UniValue & find_value(std::string_view key) const
Definition: univalue.cpp:229
enum VType getType() const
Definition: univalue.h:88
@ VNULL
Definition: univalue.h:30
@ VOBJ
Definition: univalue.h:31
@ VSTR
Definition: univalue.h:33
@ VARR
Definition: univalue.h:32
@ VNUM
Definition: univalue.h:34
@ VBOOL
Definition: univalue.h:35
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool isNull() const
Definition: univalue.h:104
const UniValue & get_obj() const
void setNull()
Definition: univalue.cpp:25
const std::string & getValStr() const
Definition: univalue.h:89
size_t size() const
Definition: univalue.h:92
enum VType type() const
Definition: univalue.h:147
const std::vector< std::string > & getKeys() const
bool empty() const
Definition: univalue.h:90
bool isStr() const
Definition: univalue.h:108
Int getInt() const
Definition: univalue.h:157
const UniValue & get_array() const
bool isNum() const
Definition: univalue.h:109
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:115
void getObjMap(std::map< std::string, UniValue > &kv) const
Definition: univalue.cpp:135
bool isObject() const
Definition: univalue.h:111
bool IsNull() const
Definition: uint256.h:32
size_type size() const
Definition: prevector.h:386
256-bit opaque blob.
Definition: uint256.h:129
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:224
std::string FormatFullVersion()
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
bool error(const char *fmt, const Args &...args)
Definition: logging.h:226
@ NONE
Definition: logging.h:39
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:280
ServiceFlags
nServices flags.
Definition: protocol.h:335
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
const char * name
Definition: rest.cpp:47
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:1273
std::vector< uint8_t > ParseHexV(const UniValue &v, std::string strName)
Definition: util.cpp:94
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:150
UniValue GetServicesNames(ServiceFlags services)
Returns, given services flags, a list of humanly readable (known) network services.
Definition: util.cpp:1337
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FillableSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:233
std::string HelpExampleRpcNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:176
static std::optional< UniValue::VType > ExpectedType(RPCArg::Type type)
Definition: util.cpp:781
UniValue JSONRPCTransactionError(TransactionError terr, const std::string &err_string)
Definition: util.cpp:333
Amount AmountFromValue(const UniValue &value)
Definition: util.cpp:55
RPCErrorCode RPCErrorFromTransactionError(TransactionError terr)
Definition: util.cpp:314
std::vector< uint8_t > ParseHexO(const UniValue &o, std::string strKey)
Definition: util.cpp:108
const std::string EXAMPLE_ADDRESS
Example CashAddr address used in multiple RPCExamples.
Definition: util.cpp:23
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:1290
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:167
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:22
std::string GetAllOutputTypes()
Definition: util.cpp:305
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:191
CPubKey AddrToPubKey(const CChainParams &chainparams, const FillableSigningProvider &keystore, const std::string &addr_in)
Definition: util.cpp:205
uint256 ParseHashO(const UniValue &o, std::string strKey)
Definition: util.cpp:90
uint256 ParseHashV(const UniValue &v, std::string strName)
Utilities: convert hex-encoded values (throws error if not hex).
Definition: util.cpp:73
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:26
static std::pair< int64_t, int64_t > ParseRange(const UniValue &value)
Definition: util.cpp:1254
std::string HelpExampleCliNamed(const std::string &methodname, const RPCArgList &args)
Definition: util.cpp:155
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:301
std::vector< std::pair< std::string, UniValue > > RPCArgList
Definition: util.h:70
static constexpr bool DEFAULT_RPC_DOC_CHECK
Definition: util.h:29
OuterType
Serializing JSON objects depends on the outer type.
Definition: util.h:118
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:53
std::vector< std::string > SplitString(std::string_view str, char sep)
Definition: string.h:22
Definition: amount.h:19
static const Currency & get()
Definition: amount.cpp:18
uint8_t decimals
Definition: amount.h:149
Definition: util.h:150
Type
Definition: util.h:151
@ 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)
@ OBJ_NAMED_PARAMS
Special type that behaves almost exactly like OBJ, defining an options object with a list of pre-defi...
const std::vector< RPCArg > m_inner
Only used for arrays or dicts.
Definition: util.h:205
const RPCArgOptions m_opts
Definition: util.h:208
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:202
const Fallback m_fallback
Definition: util.h:206
std::string ToString(bool oneline) const
Return the type string of the argument.
Definition: util.cpp:1215
UniValue MatchesType(const UniValue &request) const
Check whether the request JSON type matches.
Definition: util.cpp:814
const std::string m_description
Definition: util.h:207
bool IsOptional() const
Definition: util.cpp:843
std::string ToDescriptionString(bool is_named_arg) const
Return the description string, including the argument type and whether the argument is required.
Definition: util.cpp:851
const Type m_type
Definition: util.h:203
std::string GetName() const
Return the name, throws when there are aliases.
Definition: util.cpp:838
std::string GetFirstName() const
Return the first of all aliases.
Definition: util.cpp:834
std::string ToStringObj(bool oneline) const
Return the type string of the argument when it is in an object (dict).
Definition: util.cpp:1175
@ OMITTED
The arg is optional for one of two reasons:
@ NO
Required arg.
std::vector< std::string > type_str
Should be empty unless it is supposed to override the auto-generated type strings.
Definition: util.h:134
std::string oneline_description
Should be empty unless it is supposed to override the auto-generated summary line.
Definition: util.h:128
bool skip_type_check
Definition: util.h:125
std::string ToDescriptionString() const
Definition: util.cpp:583
const std::string m_examples
Definition: util.h:354
const std::string m_description
Definition: util.h:285
void ToSections(Sections &sections, OuterType outer_type=OuterType::NONE, const int current_indent=0) const
Append the sections of the result.
Definition: util.cpp:924
@ 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.
const std::vector< RPCResult > m_inner
Only used for arrays or dicts.
Definition: util.h:282
UniValue MatchesType(const UniValue &result) const
Check whether the result JSON type matches.
Definition: util.cpp:1072
void CheckInnerDoc() const
Definition: util.cpp:1164
const bool m_optional
Definition: util.h:283
const std::string m_key_name
Only used for dicts.
Definition: util.h:281
const Type m_type
Definition: util.h:280
const bool m_skip_type_check
Definition: util.h:284
std::string ToDescriptionString() const
Return the description string.
Definition: util.cpp:563
const std::vector< RPCResult > m_results
Definition: util.h:341
A pair of strings that can be aligned (through padding) with other Sections later on.
Definition: util.cpp:347
std::string m_left
Definition: util.cpp:350
Section(const std::string &left, const std::string &right)
Definition: util.cpp:348
const std::string m_right
Definition: util.cpp:351
Keeps track of RPCArgs by transforming them into sections for the purpose of serializing everything t...
Definition: util.cpp:358
void PushSection(const Section &s)
Definition: util.cpp:362
std::vector< Section > m_sections
Definition: util.cpp:359
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:370
size_t m_max_pad
Definition: util.cpp:360
std::string ToString() const
Concatenate all sections with proper padding.
Definition: util.cpp:445
#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:143
const char * uvTypeName(UniValue::VType t)
Definition: univalue.cpp:209