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