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