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