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