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