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