Bitcoin Core  0.21.1
P2P Digital Currency
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules
misc.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2020 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <httpserver.h>
8 #include <index/txindex.h>
9 #include <interfaces/chain.h>
10 #include <key_io.h>
11 #include <node/context.h>
12 #include <outputtype.h>
13 #include <rpc/blockchain.h>
14 #include <rpc/server.h>
15 #include <rpc/util.h>
16 #include <scheduler.h>
17 #include <script/descriptor.h>
18 #include <util/check.h>
19 #include <util/message.h> // For MessageSign(), MessageVerify()
20 #include <util/ref.h>
21 #include <util/strencodings.h>
22 #include <util/system.h>
23 
24 #include <stdint.h>
25 #include <tuple>
26 #ifdef HAVE_MALLOC_INFO
27 #include <malloc.h>
28 #endif
29 
30 #include <univalue.h>
31 
33 {
34  return RPCHelpMan{"validateaddress",
35  "\nReturn information about the given bitcoin address.\n",
36  {
37  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to validate"},
38  },
39  RPCResult{
40  RPCResult::Type::OBJ, "", "",
41  {
42  {RPCResult::Type::BOOL, "isvalid", "If the address is valid or not. If not, this is the only property returned."},
43  {RPCResult::Type::STR, "address", "The bitcoin address validated"},
44  {RPCResult::Type::STR_HEX, "scriptPubKey", "The hex-encoded scriptPubKey generated by the address"},
45  {RPCResult::Type::BOOL, "isscript", "If the key is a script"},
46  {RPCResult::Type::BOOL, "iswitness", "If the address is a witness address"},
47  {RPCResult::Type::NUM, "witness_version", /* optional */ true, "The version number of the witness program"},
48  {RPCResult::Type::STR_HEX, "witness_program", /* optional */ true, "The hex value of the witness program"},
49  }
50  },
52  HelpExampleCli("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"") +
53  HelpExampleRpc("validateaddress", "\"" + EXAMPLE_ADDRESS[0] + "\"")
54  },
55  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
56 {
57  CTxDestination dest = DecodeDestination(request.params[0].get_str());
58  bool isValid = IsValidDestination(dest);
59 
61  ret.pushKV("isvalid", isValid);
62  if (isValid)
63  {
64  std::string currentAddress = EncodeDestination(dest);
65  ret.pushKV("address", currentAddress);
66 
67  CScript scriptPubKey = GetScriptForDestination(dest);
68  ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
69 
70  UniValue detail = DescribeAddress(dest);
71  ret.pushKVs(detail);
72  }
73  return ret;
74 },
75  };
76 }
77 
79 {
80  return RPCHelpMan{"createmultisig",
81  "\nCreates a multi-signature address with n signature of m keys required.\n"
82  "It returns a json object with the address and redeemScript.\n",
83  {
84  {"nrequired", RPCArg::Type::NUM, RPCArg::Optional::NO, "The number of required signatures out of the n keys."},
85  {"keys", RPCArg::Type::ARR, RPCArg::Optional::NO, "The hex-encoded public keys.",
86  {
87  {"key", RPCArg::Type::STR_HEX, RPCArg::Optional::OMITTED, "The hex-encoded public key"},
88  }},
89  {"address_type", RPCArg::Type::STR, /* default */ "legacy", "The address type to use. Options are \"legacy\", \"p2sh-segwit\", and \"bech32\"."},
90  },
91  RPCResult{
92  RPCResult::Type::OBJ, "", "",
93  {
94  {RPCResult::Type::STR, "address", "The value of the new multisig address."},
95  {RPCResult::Type::STR_HEX, "redeemScript", "The string value of the hex-encoded redemption script."},
96  {RPCResult::Type::STR, "descriptor", "The descriptor for this multisig"},
97  }
98  },
100  "\nCreate a multisig address from 2 public keys\n"
101  + HelpExampleCli("createmultisig", "2 \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"") +
102  "\nAs a JSON-RPC call\n"
103  + HelpExampleRpc("createmultisig", "2, \"[\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd342cf11ae157a7ace5fd\\\",\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e17e107ef3f6aa5a61626\\\"]\"")
104  },
105  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
106 {
107  int required = request.params[0].get_int();
108 
109  // Get the public keys
110  const UniValue& keys = request.params[1].get_array();
111  std::vector<CPubKey> pubkeys;
112  for (unsigned int i = 0; i < keys.size(); ++i) {
113  if (IsHex(keys[i].get_str()) && (keys[i].get_str().length() == 66 || keys[i].get_str().length() == 130)) {
114  pubkeys.push_back(HexToPubKey(keys[i].get_str()));
115  } else {
116  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Invalid public key: %s\n.", keys[i].get_str()));
117  }
118  }
119 
120  // Get the output type
121  OutputType output_type = OutputType::LEGACY;
122  if (!request.params[2].isNull()) {
123  if (!ParseOutputType(request.params[2].get_str(), output_type)) {
124  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Unknown address type '%s'", request.params[2].get_str()));
125  }
126  }
127 
128  // Construct using pay-to-script-hash:
129  FillableSigningProvider keystore;
130  CScript inner;
131  const CTxDestination dest = AddAndGetMultisigDestination(required, pubkeys, output_type, keystore, inner);
132 
133  // Make the descriptor
134  std::unique_ptr<Descriptor> descriptor = InferDescriptor(GetScriptForDestination(dest), keystore);
135 
136  UniValue result(UniValue::VOBJ);
137  result.pushKV("address", EncodeDestination(dest));
138  result.pushKV("redeemScript", HexStr(inner));
139  result.pushKV("descriptor", descriptor->ToString());
140 
141  return result;
142 },
143  };
144 }
145 
147 {
148  return RPCHelpMan{"getdescriptorinfo",
149  {"\nAnalyses a descriptor.\n"},
150  {
151  {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."},
152  },
153  RPCResult{
154  RPCResult::Type::OBJ, "", "",
155  {
156  {RPCResult::Type::STR, "descriptor", "The descriptor in canonical form, without private keys"},
157  {RPCResult::Type::STR, "checksum", "The checksum for the input descriptor"},
158  {RPCResult::Type::BOOL, "isrange", "Whether the descriptor is ranged"},
159  {RPCResult::Type::BOOL, "issolvable", "Whether the descriptor is solvable"},
160  {RPCResult::Type::BOOL, "hasprivatekeys", "Whether the input descriptor contained at least one private key"},
161  }
162  },
163  RPCExamples{
164  "Analyse a descriptor\n" +
165  HelpExampleCli("getdescriptorinfo", "\"wpkh([d34db33f/84h/0h/0h]0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2dce28d959f2815b16f81798)\"")
166  },
167  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
168 {
169  RPCTypeCheck(request.params, {UniValue::VSTR});
170 
171  FlatSigningProvider provider;
172  std::string error;
173  auto desc = Parse(request.params[0].get_str(), provider, error);
174  if (!desc) {
176  }
177 
178  UniValue result(UniValue::VOBJ);
179  result.pushKV("descriptor", desc->ToString());
180  result.pushKV("checksum", GetDescriptorChecksum(request.params[0].get_str()));
181  result.pushKV("isrange", desc->IsRange());
182  result.pushKV("issolvable", desc->IsSolvable());
183  result.pushKV("hasprivatekeys", provider.keys.size() > 0);
184  return result;
185 },
186  };
187 }
188 
190 {
191  return RPCHelpMan{"deriveaddresses",
192  {"\nDerives one or more addresses corresponding to an output descriptor.\n"
193  "Examples of output descriptors are:\n"
194  " pkh(<pubkey>) P2PKH outputs for the given pubkey\n"
195  " wpkh(<pubkey>) Native segwit P2PKH outputs for the given pubkey\n"
196  " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for the given threshold and pubkeys\n"
197  " raw(<hex script>) Outputs whose scriptPubKey equals the specified hex scripts\n"
198  "\nIn the above, <pubkey> either refers to a fixed public key in hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
199  "or more path elements separated by \"/\", where \"h\" represents a hardened child key.\n"
200  "For more information on output descriptors, see the documentation in the doc/descriptors.md file.\n"},
201  {
202  {"descriptor", RPCArg::Type::STR, RPCArg::Optional::NO, "The descriptor."},
203  {"range", RPCArg::Type::RANGE, RPCArg::Optional::OMITTED_NAMED_ARG, "If a ranged descriptor is used, this specifies the end or the range (in [begin,end] notation) to derive."},
204  },
205  RPCResult{
206  RPCResult::Type::ARR, "", "",
207  {
208  {RPCResult::Type::STR, "address", "the derived addresses"},
209  }
210  },
211  RPCExamples{
212  "First three native segwit receive addresses\n" +
213  HelpExampleCli("deriveaddresses", "\"wpkh([d34db33f/84h/0h/0h]xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8PhqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKEu3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#cjjspncu\" \"[0,2]\"")
214  },
215  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
216 {
217  RPCTypeCheck(request.params, {UniValue::VSTR, UniValueType()}); // Range argument is checked later
218  const std::string desc_str = request.params[0].get_str();
219 
220  int64_t range_begin = 0;
221  int64_t range_end = 0;
222 
223  if (request.params.size() >= 2 && !request.params[1].isNull()) {
224  std::tie(range_begin, range_end) = ParseDescriptorRange(request.params[1]);
225  }
226 
227  FlatSigningProvider key_provider;
228  std::string error;
229  auto desc = Parse(desc_str, key_provider, error, /* require_checksum = */ true);
230  if (!desc) {
232  }
233 
234  if (!desc->IsRange() && request.params.size() > 1) {
235  throw JSONRPCError(RPC_INVALID_PARAMETER, "Range should not be specified for an un-ranged descriptor");
236  }
237 
238  if (desc->IsRange() && request.params.size() == 1) {
239  throw JSONRPCError(RPC_INVALID_PARAMETER, "Range must be specified for a ranged descriptor");
240  }
241 
242  UniValue addresses(UniValue::VARR);
243 
244  for (int i = range_begin; i <= range_end; ++i) {
245  FlatSigningProvider provider;
246  std::vector<CScript> scripts;
247  if (!desc->Expand(i, key_provider, scripts, provider)) {
248  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Cannot derive script without private keys"));
249  }
250 
251  for (const CScript &script : scripts) {
252  CTxDestination dest;
253  if (!ExtractDestination(script, dest)) {
254  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, strprintf("Descriptor does not have a corresponding address"));
255  }
256 
257  addresses.push_back(EncodeDestination(dest));
258  }
259  }
260 
261  // This should not be possible, but an assert seems overkill:
262  if (addresses.empty()) {
263  throw JSONRPCError(RPC_MISC_ERROR, "Unexpected empty result");
264  }
265 
266  return addresses;
267 },
268  };
269 }
270 
272 {
273  return RPCHelpMan{"verifymessage",
274  "\nVerify a signed message\n",
275  {
276  {"address", RPCArg::Type::STR, RPCArg::Optional::NO, "The bitcoin address to use for the signature."},
277  {"signature", RPCArg::Type::STR, RPCArg::Optional::NO, "The signature provided by the signer in base 64 encoding (see signmessage)."},
278  {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message that was signed."},
279  },
280  RPCResult{
281  RPCResult::Type::BOOL, "", "If the signature is verified or not."
282  },
283  RPCExamples{
284  "\nUnlock the wallet for 30 seconds\n"
285  + HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
286  "\nCreate the signature\n"
287  + HelpExampleCli("signmessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
288  "\nVerify the signature\n"
289  + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
290  "\nAs a JSON-RPC call\n"
291  + HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\", \"signature\", \"my message\"")
292  },
293  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
294 {
295  LOCK(cs_main);
296 
297  std::string strAddress = request.params[0].get_str();
298  std::string strSign = request.params[1].get_str();
299  std::string strMessage = request.params[2].get_str();
300 
301  switch (MessageVerify(strAddress, strSign, strMessage)) {
303  throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
305  throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");
307  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");
310  return false;
312  return true;
313  }
314 
315  return false;
316 },
317  };
318 }
319 
321 {
322  return RPCHelpMan{"signmessagewithprivkey",
323  "\nSign a message with the private key of an address\n",
324  {
325  {"privkey", RPCArg::Type::STR, RPCArg::Optional::NO, "The private key to sign the message with."},
326  {"message", RPCArg::Type::STR, RPCArg::Optional::NO, "The message to create a signature of."},
327  },
328  RPCResult{
329  RPCResult::Type::STR, "signature", "The signature of the message encoded in base 64"
330  },
331  RPCExamples{
332  "\nCreate the signature\n"
333  + HelpExampleCli("signmessagewithprivkey", "\"privkey\" \"my message\"") +
334  "\nVerify the signature\n"
335  + HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"signature\" \"my message\"") +
336  "\nAs a JSON-RPC call\n"
337  + HelpExampleRpc("signmessagewithprivkey", "\"privkey\", \"my message\"")
338  },
339  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
340 {
341  std::string strPrivkey = request.params[0].get_str();
342  std::string strMessage = request.params[1].get_str();
343 
344  CKey key = DecodeSecret(strPrivkey);
345  if (!key.IsValid()) {
346  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Invalid private key");
347  }
348 
349  std::string signature;
350 
351  if (!MessageSign(key, strMessage, signature)) {
352  throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
353  }
354 
355  return signature;
356 },
357  };
358 }
359 
361 {
362  return RPCHelpMan{"setmocktime",
363  "\nSet the local time to given timestamp (-regtest only)\n",
364  {
366  "Pass 0 to go back to using the system time."},
367  },
369  RPCExamples{""},
370  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
371 {
372  if (!Params().IsMockableChain()) {
373  throw std::runtime_error("setmocktime is for regression testing (-regtest mode) only");
374  }
375 
376  // For now, don't change mocktime if we're in the middle of validation, as
377  // this could have an effect on mempool time-based eviction, as well as
378  // IsCurrentForFeeEstimation() and IsInitialBlockDownload().
379  // TODO: figure out the right way to synchronize around mocktime, and
380  // ensure all call sites of GetTime() are accessing this safely.
381  LOCK(cs_main);
382 
383  RPCTypeCheck(request.params, {UniValue::VNUM});
384  const int64_t time{request.params[0].get_int64()};
385  if (time < 0) {
386  throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Mocktime can not be negative: %s.", time));
387  }
388  SetMockTime(time);
389  if (request.context.Has<NodeContext>()) {
390  for (const auto& chain_client : request.context.Get<NodeContext>().chain_clients) {
391  chain_client->setMockTime(time);
392  }
393  }
394 
395  return NullUniValue;
396 },
397  };
398 }
399 
401 {
402  return RPCHelpMan{"mockscheduler",
403  "\nBump the scheduler into the future (-regtest only)\n",
404  {
405  {"delta_time", RPCArg::Type::NUM, RPCArg::Optional::NO, "Number of seconds to forward the scheduler into the future." },
406  },
408  RPCExamples{""},
409  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
410 {
411  if (!Params().IsMockableChain()) {
412  throw std::runtime_error("mockscheduler is for regression testing (-regtest mode) only");
413  }
414 
415  // check params are valid values
416  RPCTypeCheck(request.params, {UniValue::VNUM});
417  int64_t delta_seconds = request.params[0].get_int64();
418  if ((delta_seconds <= 0) || (delta_seconds > 3600)) {
419  throw std::runtime_error("delta_time must be between 1 and 3600 seconds (1 hr)");
420  }
421 
422  // protect against null pointer dereference
423  CHECK_NONFATAL(request.context.Has<NodeContext>());
424  NodeContext& node = request.context.Get<NodeContext>();
426  node.scheduler->MockForward(std::chrono::seconds(delta_seconds));
427 
428  return NullUniValue;
429 },
430  };
431 }
432 
434 {
437  obj.pushKV("used", uint64_t(stats.used));
438  obj.pushKV("free", uint64_t(stats.free));
439  obj.pushKV("total", uint64_t(stats.total));
440  obj.pushKV("locked", uint64_t(stats.locked));
441  obj.pushKV("chunks_used", uint64_t(stats.chunks_used));
442  obj.pushKV("chunks_free", uint64_t(stats.chunks_free));
443  return obj;
444 }
445 
446 #ifdef HAVE_MALLOC_INFO
447 static std::string RPCMallocInfo()
448 {
449  char *ptr = nullptr;
450  size_t size = 0;
451  FILE *f = open_memstream(&ptr, &size);
452  if (f) {
453  malloc_info(0, f);
454  fclose(f);
455  if (ptr) {
456  std::string rv(ptr, size);
457  free(ptr);
458  return rv;
459  }
460  }
461  return "";
462 }
463 #endif
464 
466 {
467  /* Please, avoid using the word "pool" here in the RPC interface or help,
468  * as users will undoubtedly confuse it with the other "memory pool"
469  */
470  return RPCHelpMan{"getmemoryinfo",
471  "Returns an object containing information about memory usage.\n",
472  {
473  {"mode", RPCArg::Type::STR, /* default */ "\"stats\"", "determines what kind of information is returned.\n"
474  " - \"stats\" returns general statistics about memory usage in the daemon.\n"
475  " - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc 2.10+)."},
476  },
477  {
478  RPCResult{"mode \"stats\"",
479  RPCResult::Type::OBJ, "", "",
480  {
481  {RPCResult::Type::OBJ, "locked", "Information about locked memory manager",
482  {
483  {RPCResult::Type::NUM, "used", "Number of bytes used"},
484  {RPCResult::Type::NUM, "free", "Number of bytes available in current arenas"},
485  {RPCResult::Type::NUM, "total", "Total number of bytes managed"},
486  {RPCResult::Type::NUM, "locked", "Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk."},
487  {RPCResult::Type::NUM, "chunks_used", "Number allocated chunks"},
488  {RPCResult::Type::NUM, "chunks_free", "Number unused chunks"},
489  }},
490  }
491  },
492  RPCResult{"mode \"mallocinfo\"",
493  RPCResult::Type::STR, "", "\"<malloc version=\"1\">...\""
494  },
495  },
496  RPCExamples{
497  HelpExampleCli("getmemoryinfo", "")
498  + HelpExampleRpc("getmemoryinfo", "")
499  },
500  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
501 {
502  std::string mode = request.params[0].isNull() ? "stats" : request.params[0].get_str();
503  if (mode == "stats") {
505  obj.pushKV("locked", RPCLockedMemoryInfo());
506  return obj;
507  } else if (mode == "mallocinfo") {
508 #ifdef HAVE_MALLOC_INFO
509  return RPCMallocInfo();
510 #else
511  throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo is only available when compiled with glibc 2.10+");
512 #endif
513  } else {
514  throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown mode " + mode);
515  }
516 },
517  };
518 }
519 
520 static void EnableOrDisableLogCategories(UniValue cats, bool enable) {
521  cats = cats.get_array();
522  for (unsigned int i = 0; i < cats.size(); ++i) {
523  std::string cat = cats[i].get_str();
524 
525  bool success;
526  if (enable) {
527  success = LogInstance().EnableCategory(cat);
528  } else {
529  success = LogInstance().DisableCategory(cat);
530  }
531 
532  if (!success) {
533  throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat);
534  }
535  }
536 }
537 
539 {
540  return RPCHelpMan{"logging",
541  "Gets and sets the logging configuration.\n"
542  "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n"
543  "When called with arguments, adds or removes categories from debug logging and return the lists above.\n"
544  "The arguments are evaluated in order \"include\", \"exclude\".\n"
545  "If an item is both included and excluded, it will thus end up being excluded.\n"
546  "The valid logging categories are: " + LogInstance().LogCategoriesString() + "\n"
547  "In addition, the following are available as category names with special meanings:\n"
548  " - \"all\", \"1\" : represent all logging categories.\n"
549  " - \"none\", \"0\" : even if other logging categories are specified, ignore all of them.\n"
550  ,
551  {
552  {"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The categories to add to debug logging",
553  {
554  {"include_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
555  }},
556  {"exclude", RPCArg::Type::ARR, RPCArg::Optional::OMITTED_NAMED_ARG, "The categories to remove from debug logging",
557  {
558  {"exclude_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
559  }},
560  },
561  RPCResult{
562  RPCResult::Type::OBJ_DYN, "", "keys are the logging categories, and values indicates its status",
563  {
564  {RPCResult::Type::BOOL, "category", "if being debug logged or not. false:inactive, true:active"},
565  }
566  },
567  RPCExamples{
568  HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"")
569  + HelpExampleRpc("logging", "[\"all\"], [\"libevent\"]")
570  },
571  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
572 {
573  uint32_t original_log_categories = LogInstance().GetCategoryMask();
574  if (request.params[0].isArray()) {
575  EnableOrDisableLogCategories(request.params[0], true);
576  }
577  if (request.params[1].isArray()) {
578  EnableOrDisableLogCategories(request.params[1], false);
579  }
580  uint32_t updated_log_categories = LogInstance().GetCategoryMask();
581  uint32_t changed_log_categories = original_log_categories ^ updated_log_categories;
582 
583  // Update libevent logging if BCLog::LIBEVENT has changed.
584  // If the library version doesn't allow it, UpdateHTTPServerLogging() returns false,
585  // in which case we should clear the BCLog::LIBEVENT flag.
586  // Throw an error if the user has explicitly asked to change only the libevent
587  // flag and it failed.
588  if (changed_log_categories & BCLog::LIBEVENT) {
589  if (!UpdateHTTPServerLogging(LogInstance().WillLogCategory(BCLog::LIBEVENT))) {
590  LogInstance().DisableCategory(BCLog::LIBEVENT);
591  if (changed_log_categories == BCLog::LIBEVENT) {
592  throw JSONRPCError(RPC_INVALID_PARAMETER, "libevent logging cannot be updated when using libevent before v2.1.1.");
593  }
594  }
595  }
596 
597  UniValue result(UniValue::VOBJ);
598  for (const auto& logCatActive : LogInstance().LogCategoriesList()) {
599  result.pushKV(logCatActive.category, logCatActive.active);
600  }
601 
602  return result;
603 },
604  };
605 }
606 
607 static RPCHelpMan echo(const std::string& name)
608 {
609  return RPCHelpMan{name,
610  "\nSimply echo back the input arguments. This command is for testing.\n"
611  "\nIt will return an internal bug report when arg9='trigger_internal_bug' is passed.\n"
612  "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in "
613  "bitcoin-cli and the GUI. There is no server-side difference.",
614  {
625  },
626  RPCResult{RPCResult::Type::NONE, "", "Returns whatever was passed in"},
627  RPCExamples{""},
628  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
629 {
630  if (request.fHelp) throw std::runtime_error(self.ToString());
631 
632  if (request.params[9].isStr()) {
633  CHECK_NONFATAL(request.params[9].get_str() != "trigger_internal_bug");
634  }
635 
636  return request.params;
637 },
638  };
639 }
640 
641 static RPCHelpMan echo() { return echo("echo"); }
642 static RPCHelpMan echojson() { return echo("echojson"); }
643 
644 static UniValue SummaryToJSON(const IndexSummary&& summary, std::string index_name)
645 {
646  UniValue ret_summary(UniValue::VOBJ);
647  if (!index_name.empty() && index_name != summary.name) return ret_summary;
648 
649  UniValue entry(UniValue::VOBJ);
650  entry.pushKV("synced", summary.synced);
651  entry.pushKV("best_block_height", summary.best_block_height);
652  ret_summary.pushKV(summary.name, entry);
653  return ret_summary;
654 }
655 
657 {
658  return RPCHelpMan{"getindexinfo",
659  "\nReturns the status of one or all available indices currently running in the node.\n",
660  {
661  {"index_name", RPCArg::Type::STR, RPCArg::Optional::OMITTED_NAMED_ARG, "Filter results for an index with a specific name."},
662  },
663  RPCResult{
664  RPCResult::Type::OBJ, "", "", {
665  {
666  RPCResult::Type::OBJ, "name", "The name of the index",
667  {
668  {RPCResult::Type::BOOL, "synced", "Whether the index is synced or not"},
669  {RPCResult::Type::NUM, "best_block_height", "The block height to which the index is synced"},
670  }
671  },
672  },
673  },
674  RPCExamples{
675  HelpExampleCli("getindexinfo", "")
676  + HelpExampleRpc("getindexinfo", "")
677  + HelpExampleCli("getindexinfo", "txindex")
678  + HelpExampleRpc("getindexinfo", "txindex")
679  },
680  [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
681 {
682  UniValue result(UniValue::VOBJ);
683  const std::string index_name = request.params[0].isNull() ? "" : request.params[0].get_str();
684 
685  if (g_txindex) {
686  result.pushKVs(SummaryToJSON(g_txindex->GetSummary(), index_name));
687  }
688 
689  ForEachBlockFilterIndex([&result, &index_name](const BlockFilterIndex& index) {
690  result.pushKVs(SummaryToJSON(index.GetSummary(), index_name));
691  });
692 
693  return result;
694 },
695  };
696 }
697 
699 {
700 // clang-format off
701 static const CRPCCommand commands[] =
702 { // category name actor (function) argNames
703  // --------------------- ------------------------ ----------------------- ----------
704  { "control", "getmemoryinfo", &getmemoryinfo, {"mode"} },
705  { "control", "logging", &logging, {"include", "exclude"}},
706  { "util", "validateaddress", &validateaddress, {"address"} },
707  { "util", "createmultisig", &createmultisig, {"nrequired","keys","address_type"} },
708  { "util", "deriveaddresses", &deriveaddresses, {"descriptor", "range"} },
709  { "util", "getdescriptorinfo", &getdescriptorinfo, {"descriptor"} },
710  { "util", "verifymessage", &verifymessage, {"address","signature","message"} },
711  { "util", "signmessagewithprivkey", &signmessagewithprivkey, {"privkey","message"} },
712  { "util", "getindexinfo", &getindexinfo, {"index_name"} },
713 
714  /* Not shown in help */
715  { "hidden", "setmocktime", &setmocktime, {"timestamp"}},
716  { "hidden", "mockscheduler", &mockscheduler, {"delta_time"}},
717  { "hidden", "echo", &echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
718  { "hidden", "echojson", &echojson, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
719 };
720 // clang-format on
721  for (const auto& c : commands) {
722  t.appendCommand(c.name, &c);
723  }
724 }
int get_int() const
void EnableCategory(LogFlags flag)
Definition: logging.cpp:90
const std::string & get_str() const
BlockFilterIndex is used to store and retrieve block filters, hashes, and headers for a range of bloc...
size_t size() const
Definition: univalue.h:68
std::vector< std::unique_ptr< interfaces::ChainClient > > chain_clients
List of all chain clients (wallet processes or other client) connected to node.
Definition: context.h:45
void RPCTypeCheck(const UniValue &params, const std::list< UniValueType > &typesExpected, bool fAllowNull)
Type-check arguments; throws JSONRPCError if wrong type given.
Definition: util.cpp:23
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:180
BCLog::Logger & LogInstance()
Definition: logging.cpp:14
RPC command dispatcher.
Definition: server.h:137
static RPCHelpMan mockscheduler()
Definition: misc.cpp:400
Required arg.
The provided signature couldn't be parsed (maybe invalid base64).
static LockedPoolManager & Instance()
Return the current instance, or create it once.
Definition: lockedpool.h:222
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1164
static RPCHelpMan validateaddress()
Definition: misc.cpp:32
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:264
std::map< CKeyID, CKey > keys
bool empty() const
Definition: univalue.h:66
std::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
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
static RPCHelpMan createmultisig()
Definition: misc.cpp:78
#define CHECK_NONFATAL(condition)
Throw a NonFatalCheckError when the condition evaluates to false.
Definition: check.h:32
uint32_t GetCategoryMask() const
Definition: logging.h:129
void ForEachBlockFilterIndex(std::function< void(BlockFilterIndex &)> fn)
Iterate over all running block filter indexes, invoking fn on each.
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:322
The message verification was successful.
Stats stats() const
Get pool usage statistics.
Definition: lockedpool.cpp:330
bool pushKVs(const UniValue &obj)
Definition: univalue.cpp:146
OutputType
Definition: outputtype.h:17
static RPCHelpMan deriveaddresses()
Definition: misc.cpp:189
Invalid, missing or duplicate parameter.
Definition: protocol.h:43
void SetMockTime(int64_t nMockTimeIn)
For testing.
Definition: time.cpp:49
static RPCHelpMan echojson()
Definition: misc.cpp:642
std::unique_ptr< Descriptor > Parse(const std::string &descriptor, FlatSigningProvider &out, std::string &error, bool require_checksum)
Parse a descriptor string.
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:71
Special type that is a STR with only hex chars.
static UniValue SummaryToJSON(const IndexSummary &&summary, std::string index_name)
Definition: misc.cpp:644
bool MessageSign(const CKey &privkey, const std::string &message, std::string &signature)
Sign a message.
Definition: message.cpp:56
bool error(const char *fmt, const Args &...args)
Definition: system.h:52
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:51
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
Special string with only hex chars.
NodeContext struct containing references to chain state and connection state.
Definition: context.h:36
static RPCHelpMan setmocktime()
Definition: misc.cpp:360
static RPCHelpMan getindexinfo()
Definition: misc.cpp:656
#define LOCK(cs)
Definition: sync.h:230
const char * name
Definition: rest.cpp:41
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
Definition: txindex.cpp:17
Fillable signing provider that keeps keys in an address->secret map.
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:138
bool IsHex(const std::string &str)
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate...
Definition: validation.cpp:129
Unexpected type was passed as parameter.
Definition: protocol.h:40
void DisableCategory(LogFlags flag)
Definition: logging.cpp:103
General application defined errors.
Definition: protocol.h:39
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
Invalid address or key.
Definition: protocol.h:41
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:301
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FillableSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:179
static UniValue RPCLockedMemoryInfo()
Definition: misc.cpp:433
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Optional arg that is a named argument and has a default value of null.
The message was not signed with the private key of the provided address.
static void EnableOrDisableLogCategories(UniValue cats, bool enable)
Definition: misc.cpp:520
Special type that is a NUM or [NUM,NUM].
Optional argument with default value omitted because they are implicitly clear.
CTxDestination DecodeDestination(const std::string &str)
Definition: key_io.cpp:221
std::unique_ptr< Descriptor > InferDescriptor(const CScript &script, const SigningProvider &provider)
Find a descriptor for the specified script, using information from provider where possible...
const UniValue & get_array() const
static RPCHelpMan logging()
Definition: misc.cpp:538
const CChainParams & Params()
Return the currently selected parameters.
Serialized script, used inside transaction inputs and outputs.
Definition: script.h:404
void RegisterMiscRPCCommands(CRPCTable &t)
Register miscellaneous RPC commands.
Definition: misc.cpp:698
static RPCHelpMan getmemoryinfo()
Definition: misc.cpp:465
IndexSummary GetSummary() const
Get a summary of the index and its state.
Definition: base.cpp:323
The provided address is invalid.
std::string LogCategoriesString()
Returns a string with the log categories.
Definition: logging.h:140
const UniValue NullUniValue
Definition: univalue.cpp:13
std::pair< int64_t, int64_t > ParseDescriptorRange(const UniValue &value)
Parse a JSON range specified as int64, or [int64, int64].
Definition: util.cpp:813
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:133
std::string EncodeDestination(const CTxDestination &dest)
Definition: key_io.cpp:216
MessageVerificationResult MessageVerify(const std::string &address, const std::string &signature, const std::string &message)
Verify a signed message.
Definition: message.cpp:24
static RPCHelpMan verifymessage()
Definition: misc.cpp:271
An encapsulated private key.
Definition: key.h:27
Special dictionary with keys that are not literals.
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:138
static RPCHelpMan getdescriptorinfo()
Definition: misc.cpp:146
bool IsMockableChain() const
If this chain allows time to be mocked.
Definition: chainparams.h:77
A public key could not be recovered from the provided signature and message.
boost::variant< CNoDestination, PKHash, ScriptHash, WitnessV0ScriptHash, WitnessV0KeyHash, WitnessUnknown > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:214
bool isNull() const
Definition: univalue.h:77
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:268
bool ParseOutputType(const std::string &type, OutputType &output_type)
Definition: outputtype.cpp:24
const std::string EXAMPLE_ADDRESS[2]
Example bech32 addresses for the RPCExamples help documentation.
Definition: util.cpp:21
The provided address is valid but does not refer to a public key.
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:145
bool UpdateHTTPServerLogging(bool enable)
Change logging level for libevent.
Definition: httpserver.cpp:410
Memory statistics.
Definition: lockedpool.h:145
static RPCHelpMan signmessagewithprivkey()
Definition: misc.cpp:320
static RPCHelpMan echo(const std::string &name)
Definition: misc.cpp:607
std::unique_ptr< CScheduler > scheduler
Definition: context.h:49