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