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