Bitcoin ABC 0.30.7
P2P Digital Currency
misc.cpp
Go to the documentation of this file.
1// Copyright (c) 2010 Satoshi Nakamoto
2// Copyright (c) 2009-2016 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 <chainparams.h>
7#include <config.h>
8#include <consensus/amount.h>
9#include <httpserver.h>
12#include <index/txindex.h>
13#include <interfaces/chain.h>
14#include <key_io.h>
15#include <logging.h>
16#include <node/context.h>
17#include <outputtype.h>
18#include <rpc/blockchain.h>
19#include <rpc/server.h>
20#include <rpc/server_util.h>
21#include <rpc/util.h>
22#include <scheduler.h>
23#include <script/descriptor.h>
24#include <timedata.h>
25#include <util/any.h>
26#include <util/check.h>
27#include <util/message.h> // For MessageSign(), MessageVerify()
28#include <util/strencodings.h>
29#include <util/time.h>
30
31#include <univalue.h>
32
33#include <cstdint>
34#include <tuple>
35#ifdef HAVE_MALLOC_INFO
36#include <malloc.h>
37#endif
38
40
42 return RPCHelpMan{
43 "validateaddress",
44 "Return information about the given bitcoin address.\n",
45 {
47 "The bitcoin address to validate"},
48 },
51 "",
52 "",
53 {
54 {RPCResult::Type::BOOL, "isvalid",
55 "If the address is valid or not. If not, this is the only "
56 "property returned."},
57 {RPCResult::Type::STR, "address",
58 "The bitcoin address validated"},
59 {RPCResult::Type::STR_HEX, "scriptPubKey",
60 "The hex-encoded scriptPubKey generated by the address"},
61 {RPCResult::Type::BOOL, "isscript", "If the key is a script"},
62 }},
63 RPCExamples{HelpExampleCli("validateaddress", EXAMPLE_ADDRESS) +
64 HelpExampleRpc("validateaddress", EXAMPLE_ADDRESS)},
65 [&](const RPCHelpMan &self, const Config &config,
66 const JSONRPCRequest &request) -> UniValue {
67 CTxDestination dest = DecodeDestination(request.params[0].get_str(),
68 config.GetChainParams());
69 bool isValid = IsValidDestination(dest);
70
72 ret.pushKV("isvalid", isValid);
73
74 if (isValid) {
75 if (ret["address"].isNull()) {
76 std::string currentAddress =
77 EncodeDestination(dest, config);
78 ret.pushKV("address", currentAddress);
79
80 CScript scriptPubKey = GetScriptForDestination(dest);
81 ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
82
83 UniValue detail = DescribeAddress(dest);
84 ret.pushKVs(detail);
85 }
86 }
87 return ret;
88 },
89 };
90}
91
93 return RPCHelpMan{
94 "createmultisig",
95 "Creates a multi-signature address with n signature of m keys "
96 "required.\n"
97 "It returns a json object with the address and redeemScript.\n",
98 {
100 "The number of required signatures out of the n keys."},
101 {"keys",
104 "The hex-encoded public keys.",
105 {
107 "The hex-encoded public key"},
108 }},
109 },
110 RPCResult{
112 "",
113 "",
114 {
115 {RPCResult::Type::STR, "address",
116 "The value of the new multisig address."},
117 {RPCResult::Type::STR_HEX, "redeemScript",
118 "The string value of the hex-encoded redemption script."},
119 {RPCResult::Type::STR, "descriptor",
120 "The descriptor for this multisig"},
121 }},
123 "\nCreate a multisig address from 2 public keys\n" +
124 HelpExampleCli("createmultisig",
125 "2 "
126 "\"["
127 "\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd3"
128 "42cf11ae157a7ace5fd\\\","
129 "\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e1"
130 "7e107ef3f6aa5a61626\\\"]\"") +
131 "\nAs a JSON-RPC call\n" +
132 HelpExampleRpc("createmultisig",
133 "2, "
134 "\"["
135 "\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd3"
136 "42cf11ae157a7ace5fd\\\","
137 "\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e1"
138 "7e107ef3f6aa5a61626\\\"]\"")},
139 [&](const RPCHelpMan &self, const Config &config,
140 const JSONRPCRequest &request) -> UniValue {
141 int required = request.params[0].getInt<int>();
142
143 // Get the public keys
144 const UniValue &keys = request.params[1].get_array();
145 std::vector<CPubKey> pubkeys;
146 for (size_t i = 0; i < keys.size(); ++i) {
147 if ((keys[i].get_str().length() ==
149 keys[i].get_str().length() == 2 * CPubKey::SIZE) &&
150 IsHex(keys[i].get_str())) {
151 pubkeys.push_back(HexToPubKey(keys[i].get_str()));
152 } else {
154 strprintf("Invalid public key: %s\n",
155 keys[i].get_str()));
156 }
157 }
158
159 // Get the output type
160 OutputType output_type = OutputType::LEGACY;
161
162 // Construct using pay-to-script-hash:
164 CScript inner;
166 required, pubkeys, output_type, keystore, inner);
167
168 // Make the descriptor
169 std::unique_ptr<Descriptor> descriptor =
171
172 UniValue result(UniValue::VOBJ);
173 result.pushKV("address", EncodeDestination(dest, config));
174 result.pushKV("redeemScript", HexStr(inner));
175 result.pushKV("descriptor", descriptor->ToString());
176
177 return result;
178 },
179 };
180}
181
183 return RPCHelpMan{
184 "getdescriptorinfo",
185 {"Analyses a descriptor.\n"},
186 {
188 "The descriptor."},
189 },
190 RPCResult{
192 "",
193 "",
194 {
195 {RPCResult::Type::STR, "descriptor",
196 "The descriptor in canonical form, without private keys"},
197 {RPCResult::Type::STR, "checksum",
198 "The checksum for the input descriptor"},
199 {RPCResult::Type::BOOL, "isrange",
200 "Whether the descriptor is ranged"},
201 {RPCResult::Type::BOOL, "issolvable",
202 "Whether the descriptor is solvable"},
203 {RPCResult::Type::BOOL, "hasprivatekeys",
204 "Whether the input descriptor contained at least one private "
205 "key"},
206 }},
207 RPCExamples{"Analyse a descriptor\n" +
208 HelpExampleCli("getdescriptorinfo",
209 "\"pkh([d34db33f/84h/0h/"
210 "0h]"
211 "0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2"
212 "dce28d959f2815b16f81798)\"")},
213 [&](const RPCHelpMan &self, const Config &config,
214 const JSONRPCRequest &request) -> UniValue {
215 FlatSigningProvider provider;
216 std::string error;
217 auto desc = Parse(request.params[0].get_str(), provider, error);
218 if (!desc) {
220 }
221
222 UniValue result(UniValue::VOBJ);
223 result.pushKV("descriptor", desc->ToString());
224 result.pushKV("checksum",
225 GetDescriptorChecksum(request.params[0].get_str()));
226 result.pushKV("isrange", desc->IsRange());
227 result.pushKV("issolvable", desc->IsSolvable());
228 result.pushKV("hasprivatekeys", provider.keys.size() > 0);
229 return result;
230 },
231 };
232}
233
235 return RPCHelpMan{
236 "deriveaddresses",
237 {"Derives one or more addresses corresponding to an output "
238 "descriptor.\n"
239 "Examples of output descriptors are:\n"
240 " pkh(<pubkey>) P2PKH outputs for the given "
241 "pubkey\n"
242 " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for "
243 "the given threshold and pubkeys\n"
244 " raw(<hex script>) Outputs whose scriptPubKey "
245 "equals the specified hex scripts\n"
246 "\nIn the above, <pubkey> either refers to a fixed public key in "
247 "hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
248 "or more path elements separated by \"/\", where \"h\" represents a "
249 "hardened child key.\n"
250 "For more information on output descriptors, see the documentation in "
251 "the doc/descriptors.md file.\n"},
252 {
254 "The descriptor."},
256 "If a ranged descriptor is used, this specifies the end or the "
257 "range (in [begin,end] notation) to derive."},
258 },
259 RPCResult{
261 "",
262 "",
263 {
264 {RPCResult::Type::STR, "address", "the derived addresses"},
265 }},
266 RPCExamples{"First three pkh receive addresses\n" +
268 "deriveaddresses",
269 "\"pkh([d34db33f/84h/0h/0h]"
270 "xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8P"
271 "hqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKE"
272 "u3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#3vhfv5h5\" \"[0,2]\"")},
273 [&](const RPCHelpMan &self, const Config &config,
274 const JSONRPCRequest &request) -> UniValue {
275 const std::string desc_str = request.params[0].get_str();
276
277 int64_t range_begin = 0;
278 int64_t range_end = 0;
279
280 if (request.params.size() >= 2 && !request.params[1].isNull()) {
281 std::tie(range_begin, range_end) =
282 ParseDescriptorRange(request.params[1]);
283 }
284
285 FlatSigningProvider key_provider;
286 std::string error;
287 auto desc = Parse(desc_str, key_provider, error,
288 /* require_checksum = */ true);
289 if (!desc) {
291 }
292
293 if (!desc->IsRange() && request.params.size() > 1) {
295 "Range should not be specified for an "
296 "un-ranged descriptor");
297 }
298
299 if (desc->IsRange() && request.params.size() == 1) {
300 throw JSONRPCError(
302 "Range must be specified for a ranged descriptor");
303 }
304
305 UniValue addresses(UniValue::VARR);
306
307 for (int i = range_begin; i <= range_end; ++i) {
308 FlatSigningProvider provider;
309 std::vector<CScript> scripts;
310 if (!desc->Expand(i, key_provider, scripts, provider)) {
311 throw JSONRPCError(
313 strprintf("Cannot derive script without private keys"));
314 }
315
316 for (const CScript &script : scripts) {
317 CTxDestination dest;
318 if (!ExtractDestination(script, dest)) {
319 throw JSONRPCError(
321 strprintf("Descriptor does not have a "
322 "corresponding address"));
323 }
324
325 addresses.push_back(EncodeDestination(dest, config));
326 }
327 }
328
329 // This should not be possible, but an assert seems overkill:
330 if (addresses.empty()) {
331 throw JSONRPCError(RPC_MISC_ERROR, "Unexpected empty result");
332 }
333
334 return addresses;
335 },
336 };
337}
338
340 return RPCHelpMan{
341 "verifymessage",
342 "Verify a signed message\n",
343 {
345 "The bitcoin address to use for the signature."},
347 "The signature provided by the signer in base 64 encoding (see "
348 "signmessage)."},
350 "The message that was signed."},
351 },
353 "If the signature is verified or not."},
355 "\nUnlock the wallet for 30 seconds\n" +
356 HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
357 "\nCreate the signature\n" +
359 "signmessage",
360 "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
361 "\nVerify the signature\n" +
362 HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
363 "XX\" \"signature\" \"my "
364 "message\"") +
365 "\nAs a JSON-RPC call\n" +
366 HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
367 "XX\", \"signature\", \"my "
368 "message\"")},
369 [&](const RPCHelpMan &self, const Config &config,
370 const JSONRPCRequest &request) -> UniValue {
371 LOCK(cs_main);
372
373 std::string strAddress = request.params[0].get_str();
374 std::string strSign = request.params[1].get_str();
375 std::string strMessage = request.params[2].get_str();
376
377 switch (MessageVerify(config.GetChainParams(), strAddress, strSign,
378 strMessage)) {
380 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
383 "Address does not refer to key");
386 "Malformed base64 encoding");
389 return false;
391 return true;
392 }
393
394 return false;
395 },
396 };
397}
398
400 return RPCHelpMan{
401 "signmessagewithprivkey",
402 "Sign a message with the private key of an address\n",
403 {
405 "The private key to sign the message with."},
407 "The message to create a signature of."},
408 },
409 RPCResult{RPCResult::Type::STR, "signature",
410 "The signature of the message encoded in base 64"},
411 RPCExamples{"\nCreate the signature\n" +
412 HelpExampleCli("signmessagewithprivkey",
413 "\"privkey\" \"my message\"") +
414 "\nVerify the signature\n" +
415 HelpExampleCli("verifymessage",
416 "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" "
417 "\"signature\" \"my message\"") +
418 "\nAs a JSON-RPC call\n" +
419 HelpExampleRpc("signmessagewithprivkey",
420 "\"privkey\", \"my message\"")},
421 [&](const RPCHelpMan &self, const Config &config,
422 const JSONRPCRequest &request) -> UniValue {
423 std::string strPrivkey = request.params[0].get_str();
424 std::string strMessage = request.params[1].get_str();
425
426 CKey key = DecodeSecret(strPrivkey);
427 if (!key.IsValid()) {
429 "Invalid private key");
430 }
431
432 std::string signature;
433
434 if (!MessageSign(key, strMessage, signature)) {
435 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
436 }
437
438 return signature;
439 },
440 };
441}
442
444 return RPCHelpMan{
445 "setmocktime",
446 "Set the local time to given timestamp (-regtest only)\n",
447 {
449 UNIX_EPOCH_TIME + "\n"
450 "Pass 0 to go back to using the system time."},
451 },
453 RPCExamples{""},
454 [&](const RPCHelpMan &self, const Config &config,
455 const JSONRPCRequest &request) -> UniValue {
456 if (!config.GetChainParams().IsMockableChain()) {
457 throw std::runtime_error(
458 "setmocktime for regression testing (-regtest mode) only");
459 }
460
461 // For now, don't change mocktime if we're in the middle of
462 // validation, as this could have an effect on mempool time-based
463 // eviction, as well as IsInitialBlockDownload().
464 // TODO: figure out the right way to synchronize around mocktime,
465 // and ensure all call sites of GetTime() are accessing this safely.
466 LOCK(cs_main);
467
468 const int64_t time{request.params[0].getInt<int64_t>()};
469 if (time < 0) {
470 throw JSONRPCError(
472 strprintf("Mocktime can not be negative: %s.", time));
473 }
474 SetMockTime(time);
475 auto node_context = util::AnyPtr<NodeContext>(request.context);
476 if (node_context) {
477 for (const auto &chain_client : node_context->chain_clients) {
478 chain_client->setMockTime(time);
479 }
480 }
481
482 return NullUniValue;
483 },
484 };
485}
486
488 return RPCHelpMan{
489 "mockscheduler",
490 "Bump the scheduler into the future (-regtest only)\n",
491 {
493 "Number of seconds to forward the scheduler into the future."},
494 },
496 RPCExamples{""},
497 [&](const RPCHelpMan &self, const Config &config,
498 const JSONRPCRequest &request) -> UniValue {
499 if (!Params().IsMockableChain()) {
500 throw std::runtime_error("mockscheduler is for regression "
501 "testing (-regtest mode) only");
502 }
503
504 int64_t delta_seconds = request.params[0].getInt<int64_t>();
505 if ((delta_seconds <= 0) || (delta_seconds > 3600)) {
506 throw std::runtime_error(
507 "delta_time must be between 1 and 3600 seconds (1 hr)");
508 }
509
510 auto node_context =
511 CHECK_NONFATAL(util::AnyPtr<NodeContext>(request.context));
512 // protect against null pointer dereference
513 CHECK_NONFATAL(node_context->scheduler);
514 node_context->scheduler->MockForward(
515 std::chrono::seconds(delta_seconds));
516
517 return NullUniValue;
518 },
519 };
520}
521
525 obj.pushKV("used", uint64_t(stats.used));
526 obj.pushKV("free", uint64_t(stats.free));
527 obj.pushKV("total", uint64_t(stats.total));
528 obj.pushKV("locked", uint64_t(stats.locked));
529 obj.pushKV("chunks_used", uint64_t(stats.chunks_used));
530 obj.pushKV("chunks_free", uint64_t(stats.chunks_free));
531 return obj;
532}
533
534#ifdef HAVE_MALLOC_INFO
535static std::string RPCMallocInfo() {
536 char *ptr = nullptr;
537 size_t size = 0;
538 FILE *f = open_memstream(&ptr, &size);
539 if (f) {
540 malloc_info(0, f);
541 fclose(f);
542 if (ptr) {
543 std::string rv(ptr, size);
544 free(ptr);
545 return rv;
546 }
547 }
548 return "";
549}
550#endif
551
553 /* Please, avoid using the word "pool" here in the RPC interface or help,
554 * as users will undoubtedly confuse it with the other "memory pool"
555 */
556 return RPCHelpMan{
557 "getmemoryinfo",
558 "Returns an object containing information about memory usage.\n",
559 {
560 {"mode", RPCArg::Type::STR, RPCArg::Default{"stats"},
561 "determines what kind of information is returned.\n"
562 " - \"stats\" returns general statistics about memory usage in "
563 "the daemon.\n"
564 " - \"mallocinfo\" returns an XML string describing low-level "
565 "heap state (only available if compiled with glibc 2.10+)."},
566 },
567 {
568 RPCResult{
569 "mode \"stats\"",
571 "",
572 "",
573 {
575 "locked",
576 "Information about locked memory manager",
577 {
578 {RPCResult::Type::NUM, "used", "Number of bytes used"},
579 {RPCResult::Type::NUM, "free",
580 "Number of bytes available in current arenas"},
581 {RPCResult::Type::NUM, "total",
582 "Total number of bytes managed"},
583 {RPCResult::Type::NUM, "locked",
584 "Amount of bytes that succeeded locking. If this "
585 "number is smaller than total, locking pages failed "
586 "at some point and key data could be swapped to "
587 "disk."},
588 {RPCResult::Type::NUM, "chunks_used",
589 "Number allocated chunks"},
590 {RPCResult::Type::NUM, "chunks_free",
591 "Number unused chunks"},
592 }},
593 }},
594 RPCResult{"mode \"mallocinfo\"", RPCResult::Type::STR, "",
595 "\"<malloc version=\"1\">...\""},
596 },
597 RPCExamples{HelpExampleCli("getmemoryinfo", "") +
598 HelpExampleRpc("getmemoryinfo", "")},
599 [&](const RPCHelpMan &self, const Config &config,
600 const JSONRPCRequest &request) -> UniValue {
601 std::string mode = request.params[0].isNull()
602 ? "stats"
603 : request.params[0].get_str();
604 if (mode == "stats") {
606 obj.pushKV("locked", RPCLockedMemoryInfo());
607 return obj;
608 } else if (mode == "mallocinfo") {
609#ifdef HAVE_MALLOC_INFO
610 return RPCMallocInfo();
611#else
613 "mallocinfo is only available when compiled "
614 "with glibc 2.10+");
615#endif
616 } else {
618 "unknown mode " + mode);
619 }
620 },
621 };
622}
623
624static void EnableOrDisableLogCategories(UniValue cats, bool enable) {
625 cats = cats.get_array();
626 for (size_t i = 0; i < cats.size(); ++i) {
627 std::string cat = cats[i].get_str();
628
629 bool success;
630 if (enable) {
631 success = LogInstance().EnableCategory(cat);
632 } else {
633 success = LogInstance().DisableCategory(cat);
634 }
635
636 if (!success) {
638 "unknown logging category " + cat);
639 }
640 }
641}
642
644 return RPCHelpMan{
645 "logging",
646 "Gets and sets the logging configuration.\n"
647 "When called without an argument, returns the list of categories with "
648 "status that are currently being debug logged or not.\n"
649 "When called with arguments, adds or removes categories from debug "
650 "logging and return the lists above.\n"
651 "The arguments are evaluated in order \"include\", \"exclude\".\n"
652 "If an item is both included and excluded, it will thus end up being "
653 "excluded.\n"
654 "The valid logging categories are: " +
656 "\n"
657 "In addition, the following are available as category names with "
658 "special meanings:\n"
659 " - \"all\", \"1\" : represent all logging categories.\n"
660 " - \"none\", \"0\" : even if other logging categories are "
661 "specified, ignore all of them.\n",
662 {
663 {"include",
666 "The categories to add to debug logging",
667 {
668 {"include_category", RPCArg::Type::STR,
669 RPCArg::Optional::OMITTED, "the valid logging category"},
670 }},
671 {"exclude",
674 "The categories to remove from debug logging",
675 {
676 {"exclude_category", RPCArg::Type::STR,
677 RPCArg::Optional::OMITTED, "the valid logging category"},
678 }},
679 },
680 RPCResult{
682 "",
683 "keys are the logging categories, and values indicates its status",
684 {
685 {RPCResult::Type::BOOL, "category",
686 "if being debug logged or not. false:inactive, true:active"},
687 }},
689 HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") +
690 HelpExampleRpc("logging", "[\"all\"], [\"libevent\"]")},
691 [&](const RPCHelpMan &self, const Config &config,
692 const JSONRPCRequest &request) -> UniValue {
693 uint32_t original_log_categories = LogInstance().GetCategoryMask();
694 if (request.params[0].isArray()) {
695 EnableOrDisableLogCategories(request.params[0], true);
696 }
697
698 if (request.params[1].isArray()) {
699 EnableOrDisableLogCategories(request.params[1], false);
700 }
701
702 uint32_t updated_log_categories = LogInstance().GetCategoryMask();
703 uint32_t changed_log_categories =
704 original_log_categories ^ updated_log_categories;
705
706 // Update libevent logging if BCLog::LIBEVENT has changed.
707 if (changed_log_categories & BCLog::LIBEVENT) {
709 LogInstance().WillLogCategory(BCLog::LIBEVENT));
710 }
711
712 UniValue result(UniValue::VOBJ);
713 for (const auto &logCatActive : LogInstance().LogCategoriesList()) {
714 result.pushKV(logCatActive.category, logCatActive.active);
715 }
716
717 return result;
718 },
719 };
720}
721
722static RPCHelpMan echo(const std::string &name) {
723 return RPCHelpMan{
724 name,
725 "Simply echo back the input arguments. This command is for "
726 "testing.\n"
727 "\nIt will return an internal bug report when "
728 "arg9='trigger_internal_bug' is passed.\n"
729 "\nThe difference between echo and echojson is that echojson has "
730 "argument conversion enabled in the client-side table in "
731 "bitcoin-cli and the GUI. There is no server-side difference.",
732 {
753 },
754 RPCResult{RPCResult::Type::ANY, "", "Returns whatever was passed in"},
755 RPCExamples{""},
756 [&](const RPCHelpMan &self, const Config &config,
757 const JSONRPCRequest &request) -> UniValue {
758 if (request.params[9].isStr()) {
759 CHECK_NONFATAL(request.params[9].get_str() !=
760 "trigger_internal_bug");
761 }
762
763 return request.params;
764 },
765 };
766}
767
768static RPCHelpMan echo() {
769 return echo("echo");
770}
772 return echo("echojson");
773}
774
776 return RPCHelpMan{
777 "getcurrencyinfo",
778 "Returns an object containing information about the currency.\n",
779 {},
780 {
781 RPCResult{
783 "",
784 "",
785 {
786 {RPCResult::Type::STR, "ticker", "Ticker symbol"},
787 {RPCResult::Type::NUM, "satoshisperunit",
788 "Number of satoshis per base unit"},
789 {RPCResult::Type::NUM, "decimals",
790 "Number of digits to the right of the decimal point."},
791 }},
792 },
793 RPCExamples{HelpExampleCli("getcurrencyinfo", "") +
794 HelpExampleRpc("getcurrencyinfo", "")},
795 [&](const RPCHelpMan &self, const Config &config,
796 const JSONRPCRequest &request) -> UniValue {
797 const Currency &currency = Currency::get();
798
800 res.pushKV("ticker", currency.ticker);
801 res.pushKV("satoshisperunit", currency.baseunit / SATOSHI);
802 res.pushKV("decimals", currency.decimals);
803 return res;
804 },
805 };
806}
807
808static UniValue SummaryToJSON(const IndexSummary &&summary,
809 std::string index_name) {
810 UniValue ret_summary(UniValue::VOBJ);
811 if (!index_name.empty() && index_name != summary.name) {
812 return ret_summary;
813 }
814
816 entry.pushKV("synced", summary.synced);
817 entry.pushKV("best_block_height", summary.best_block_height);
818 ret_summary.pushKV(summary.name, entry);
819 return ret_summary;
820}
821
823 return RPCHelpMan{
824 "getindexinfo",
825 "Returns the status of one or all available indices currently "
826 "running in the node.\n",
827 {
828 {"index_name", RPCArg::Type::STR,
830 "Filter results for an index with a specific name."},
831 },
832 RPCResult{
834 "",
835 "",
836 {
838 "name",
839 "The name of the index",
840 {
841 {RPCResult::Type::BOOL, "synced",
842 "Whether the index is synced or not"},
843 {RPCResult::Type::NUM, "best_block_height",
844 "The block height to which the index is synced"},
845 }},
846 },
847 },
848 RPCExamples{HelpExampleCli("getindexinfo", "") +
849 HelpExampleRpc("getindexinfo", "") +
850 HelpExampleCli("getindexinfo", "txindex") +
851 HelpExampleRpc("getindexinfo", "txindex")},
852 [&](const RPCHelpMan &self, const Config &config,
853 const JSONRPCRequest &request) -> UniValue {
854 UniValue result(UniValue::VOBJ);
855 const std::string index_name =
856 request.params[0].isNull() ? "" : request.params[0].get_str();
857
858 if (g_txindex) {
859 result.pushKVs(
860 SummaryToJSON(g_txindex->GetSummary(), index_name));
861 }
862
863 if (g_coin_stats_index) {
864 result.pushKVs(SummaryToJSON(g_coin_stats_index->GetSummary(),
865 index_name));
866 }
867
868 ForEachBlockFilterIndex([&result, &index_name](
869 const BlockFilterIndex &index) {
870 result.pushKVs(SummaryToJSON(index.GetSummary(), index_name));
871 });
872
873 return result;
874 },
875 };
876}
877
879 return RPCHelpMan{
880 "gettime",
881 "Returns the node time information\n",
882 {},
883 RPCResult{
885 "time",
886 "",
887 {
888 {RPCResult::Type::NUM, "local", "The node local timestamp"},
889 {RPCResult::Type::NUM, "offset",
890 "The time offset gathered from the other nodes on the "
891 "network"},
892 {RPCResult::Type::NUM, "adjusted",
893 "The adjusted timestamp of this node"},
894 },
895 },
896 RPCExamples{HelpExampleCli("gettime", "") +
897 HelpExampleRpc("gettime", "")},
898 [&](const RPCHelpMan &self, const Config &config,
899 const JSONRPCRequest &request) -> UniValue {
900 UniValue timeObj(UniValue::VOBJ);
901 timeObj.pushKV("local", GetTime());
902 timeObj.pushKV("offset", GetTimeOffset());
903 timeObj.pushKV("adjusted", TicksSinceEpoch<std::chrono::seconds>(
904 GetAdjustedTime()));
905 return timeObj;
906 },
907 };
908}
909
911 return RPCHelpMan{
912 "getinfo",
913 "Returns basic information about the node\n",
914 {},
915 RPCResult{
917 "info",
918 "",
919 {
920 {RPCResult::Type::STR_HEX, "version_number",
921 "The version number"},
922 {RPCResult::Type::STR, "version_full",
923 "The full version as a string"},
924 {RPCResult::Type::BOOL, "avalanche",
925 "Wether avalanche is enabled"},
926 },
927 },
928 RPCExamples{HelpExampleCli("getinfo", "") +
929 HelpExampleRpc("getinfo", "")},
930 [&](const RPCHelpMan &self, const Config &config,
931 const JSONRPCRequest &request) -> UniValue {
932 NodeContext &node = EnsureAnyNodeContext(request.context);
933
934 UniValue infoObj(UniValue::VOBJ);
935 infoObj.pushKV("version_number", CLIENT_VERSION);
936 infoObj.pushKV("version_full", FormatFullVersion());
937 infoObj.pushKV("avalanche", !!node.avalanche);
938 return infoObj;
939 },
940 };
941}
942
944 // clang-format off
945 static const CRPCCommand commands[] = {
946 // category actor (function)
947 // ------------------ ----------------------
948 { "control", getmemoryinfo, },
949 { "control", logging, },
950 { "util", validateaddress, },
951 { "util", createmultisig, },
952 { "util", deriveaddresses, },
953 { "util", getdescriptorinfo, },
954 { "util", verifymessage, },
955 { "util", signmessagewithprivkey, },
956 { "util", getcurrencyinfo, },
957 { "util", getindexinfo, },
958 { "util", gettime, },
959 { "util", getinfo, },
960
961 /* Not shown in help */
962 { "hidden", setmocktime, },
963 { "hidden", mockscheduler, },
964 { "hidden", echo, },
965 { "hidden", echojson, },
966 };
967 // clang-format on
968 for (const auto &c : commands) {
969 t.appendCommand(c.name, &c);
970 }
971}
static constexpr Amount SATOSHI
Definition: amount.h:143
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.
Definition: chainparams.cpp:19
#define CHECK_NONFATAL(condition)
Identity function.
Definition: check.h:53
void DisableCategory(LogFlags category)
Definition: logging.cpp:387
void EnableCategory(LogFlags category)
Definition: logging.cpp:374
uint32_t GetCategoryMask() const
Definition: logging.h:159
std::string LogCategoriesString() const
Returns a string with the log categories in alphabetical order.
Definition: logging.h:172
IndexSummary GetSummary() const
Get a summary of the index and its state.
Definition: base.cpp:400
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:113
An encapsulated secp256k1 private key.
Definition: key.h:28
bool IsValid() const
Check whether this private key is valid.
Definition: key.h:97
static constexpr unsigned int COMPRESSED_SIZE
Definition: pubkey.h:37
static constexpr unsigned int SIZE
secp256k1:
Definition: pubkey.h:36
RPC command dispatcher.
Definition: server.h:194
void appendCommand(const std::string &name, const CRPCCommand *pcmd)
Appends a CRPCCommand to the dispatch table.
Definition: server.cpp:327
Definition: config.h:19
Fillable signing provider that keeps keys in an address->secret map.
Stats stats() const
Get pool usage statistics.
Definition: lockedpool.cpp:332
static LockedPoolManager & Instance()
Return the current instance, or create it once.
Definition: lockedpool.h:236
void push_back(UniValue val)
Definition: univalue.cpp:96
const std::string & get_str() const
@ VOBJ
Definition: univalue.h:31
@ VARR
Definition: univalue.h:32
bool isNull() const
Definition: univalue.h:104
size_t size() const
Definition: univalue.h:92
void pushKVs(UniValue obj)
Definition: univalue.cpp:126
bool empty() const
Definition: univalue.h:90
Int getInt() const
Definition: univalue.h:157
const UniValue & get_array() const
void pushKV(std::string key, UniValue val)
Definition: univalue.cpp:115
static UniValue Parse(std::string_view raw)
Parse string to UniValue or throw runtime_error if string contains invalid JSON.
Definition: client.cpp:225
std::string FormatFullVersion()
static constexpr int CLIENT_VERSION
bitcoind-res.rc includes this file, but it cannot cope with real c++ code.
Definition: clientversion.h:38
std::unique_ptr< CoinStatsIndex > g_coin_stats_index
The global UTXO set hash object.
RecursiveMutex cs_main
Mutex to guard access to validation specific variables, such as reading or changing the chainstate.
Definition: cs_main.cpp:7
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::string GetDescriptorChecksum(const std::string &descriptor)
Get the checksum for a descriptor.
void UpdateHTTPServerLogging(bool enable)
Change logging level for libevent.
Definition: httpserver.cpp:534
std::string EncodeDestination(const CTxDestination &dest, const Config &config)
Definition: key_io.cpp:167
CTxDestination DecodeDestination(const std::string &addr, const CChainParams &params)
Definition: key_io.cpp:174
CKey DecodeSecret(const std::string &str)
Definition: key_io.cpp:77
BCLog::Logger & LogInstance()
Definition: logging.cpp:21
bool error(const char *fmt, const Args &...args)
Definition: logging.h:263
MessageVerificationResult MessageVerify(const CChainParams &params, const std::string &address, const std::string &signature, const std::string &message)
Verify a signed message.
Definition: message.cpp:24
bool MessageSign(const CKey &privkey, const std::string &message, std::string &signature)
Sign a message.
Definition: message.cpp:54
@ 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:643
static RPCHelpMan setmocktime()
Definition: misc.cpp:443
void RegisterMiscRPCCommands(CRPCTable &t)
Definition: misc.cpp:943
static RPCHelpMan getinfo()
Definition: misc.cpp:910
static void EnableOrDisableLogCategories(UniValue cats, bool enable)
Definition: misc.cpp:624
static UniValue RPCLockedMemoryInfo()
Definition: misc.cpp:522
static RPCHelpMan mockscheduler()
Definition: misc.cpp:487
static RPCHelpMan getmemoryinfo()
Definition: misc.cpp:552
static RPCHelpMan getcurrencyinfo()
Definition: misc.cpp:775
static RPCHelpMan getdescriptorinfo()
Definition: misc.cpp:182
static RPCHelpMan echo(const std::string &name)
Definition: misc.cpp:722
static UniValue SummaryToJSON(const IndexSummary &&summary, std::string index_name)
Definition: misc.cpp:808
static RPCHelpMan gettime()
Definition: misc.cpp:878
static RPCHelpMan echojson()
Definition: misc.cpp:771
static RPCHelpMan deriveaddresses()
Definition: misc.cpp:234
static RPCHelpMan signmessagewithprivkey()
Definition: misc.cpp:399
static RPCHelpMan createmultisig()
Definition: misc.cpp:92
static RPCHelpMan verifymessage()
Definition: misc.cpp:339
static RPCHelpMan validateaddress()
Definition: misc.cpp:41
static RPCHelpMan getindexinfo()
Definition: misc.cpp:822
@ LIBEVENT
Definition: logging.h:57
static bool isNull(const AnyVoteItem &item)
Definition: processor.cpp:412
Definition: init.h:28
OutputType
Definition: outputtype.h:16
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:58
const char * name
Definition: rest.cpp:47
@ RPC_MISC_ERROR
General application defined errors std::exception thrown in command handling.
Definition: protocol.h:38
@ RPC_TYPE_ERROR
Unexpected type was passed as parameter.
Definition: protocol.h:40
@ RPC_INVALID_PARAMETER
Invalid, missing or duplicate parameter.
Definition: protocol.h:46
@ RPC_INVALID_ADDRESS_OR_KEY
Invalid address or key.
Definition: protocol.h:42
std::pair< int64_t, int64_t > ParseDescriptorRange(const UniValue &value)
Parse a JSON range specified as int64, or [int64, int64].
Definition: util.cpp:1273
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:150
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FillableSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:233
const std::string EXAMPLE_ADDRESS
Example CashAddr address used in multiple RPCExamples.
Definition: util.cpp:23
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:167
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:22
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:191
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:301
NodeContext & EnsureAnyNodeContext(const std::any &context)
Definition: server_util.cpp:21
bool ExtractDestination(const CScript &scriptPubKey, CTxDestination &addressRet)
Parse a standard scriptPubKey for the destination address.
Definition: standard.cpp:158
bool IsValidDestination(const CTxDestination &dest)
Check whether a CTxDestination is a CNoDestination.
Definition: standard.cpp:260
CScript GetScriptForDestination(const CTxDestination &dest)
Generate a Bitcoin scriptPubKey for the given CTxDestination.
Definition: standard.cpp:240
std::variant< CNoDestination, PKHash, ScriptHash > CTxDestination
A txout script template with a specific destination.
Definition: standard.h:85
Amount baseunit
Definition: amount.h:147
static const Currency & get()
Definition: amount.cpp:18
std::string ticker
Definition: amount.h:150
uint8_t decimals
Definition: amount.h:149
std::map< CKeyID, CKey > keys
Memory statistics.
Definition: lockedpool.h:153
@ RANGE
Special type that is a NUM or [NUM,NUM].
@ STR_HEX
Special type that is a STR with only hex chars.
@ OMITTED
The arg is optional for one of two reasons:
@ NO
Required arg.
bool skip_type_check
Definition: util.h:125
@ 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.
NodeContext struct containing references to chain state and connection state.
Definition: context.h:43
#define LOCK(cs)
Definition: sync.h:306
int64_t GetTime()
DEPRECATED Use either ClockType::now() or Now<TimePointType>() if a cast is needed.
Definition: time.cpp:109
void SetMockTime(int64_t nMockTimeIn)
DEPRECATED Use SetMockTime with chrono type.
Definition: time.cpp:89
int64_t GetTimeOffset()
"Never go to sea with two chronometers; take one or three." Our three time sources are:
Definition: timedata.cpp:30
NodeClock::time_point GetAdjustedTime()
Definition: timedata.cpp:35
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1202
std::unique_ptr< TxIndex > g_txindex
The global transaction index, used in GetTransaction. May be null.
Definition: txindex.cpp:16
const UniValue NullUniValue
Definition: univalue.cpp:16
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
bool IsHex(std::string_view str)
Returns true if each character in str is a hex character, and has an even number of hex digits.