Bitcoin ABC 0.32.5
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 <config.h>
12#include <consensus/amount.h>
13#include <httpserver.h>
16#include <index/txindex.h>
17#include <interfaces/chain.h>
18#include <key_io.h>
19#include <logging.h>
20#include <node/context.h>
21#include <outputtype.h>
23#include <rpc/blockchain.h>
24#include <rpc/server.h>
25#include <rpc/server_util.h>
26#include <rpc/util.h>
27#include <scheduler.h>
28#include <script/descriptor.h>
29#include <timedata.h>
30#include <util/any.h>
31#include <util/check.h>
32#include <util/message.h> // For MessageSign(), MessageVerify()
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
509 int64_t delta_seconds = request.params[0].getInt<int64_t>();
510 if ((delta_seconds <= 0) || (delta_seconds > 3600)) {
511 throw std::runtime_error(
512 "delta_time must be between 1 and 3600 seconds (1 hr)");
513 }
514
515 auto node_context =
516 CHECK_NONFATAL(util::AnyPtr<NodeContext>(request.context));
517 // protect against null pointer dereference
518 CHECK_NONFATAL(node_context->scheduler);
519 node_context->scheduler->MockForward(
520 std::chrono::seconds(delta_seconds));
521
522 return NullUniValue;
523 },
524 };
525}
526
530 obj.pushKV("used", uint64_t(stats.used));
531 obj.pushKV("free", uint64_t(stats.free));
532 obj.pushKV("total", uint64_t(stats.total));
533 obj.pushKV("locked", uint64_t(stats.locked));
534 obj.pushKV("chunks_used", uint64_t(stats.chunks_used));
535 obj.pushKV("chunks_free", uint64_t(stats.chunks_free));
536 return obj;
537}
538
539#ifdef HAVE_MALLOC_INFO
540static std::string RPCMallocInfo() {
541 char *ptr = nullptr;
542 size_t size = 0;
543 FILE *f = open_memstream(&ptr, &size);
544 if (f) {
545 malloc_info(0, f);
546 fclose(f);
547 if (ptr) {
548 std::string rv(ptr, size);
549 free(ptr);
550 return rv;
551 }
552 }
553 return "";
554}
555#endif
556
558 /* Please, avoid using the word "pool" here in the RPC interface or help,
559 * as users will undoubtedly confuse it with the other "memory pool"
560 */
561 return RPCHelpMan{
562 "getmemoryinfo",
563 "Returns an object containing information about memory usage.\n",
564 {
565 {"mode", RPCArg::Type::STR, RPCArg::Default{"stats"},
566 "determines what kind of information is returned.\n"
567 " - \"stats\" returns general statistics about memory usage in "
568 "the daemon.\n"
569 " - \"mallocinfo\" returns an XML string describing low-level "
570 "heap state (only available if compiled with glibc 2.10+)."},
571 },
572 {
573 RPCResult{
574 "mode \"stats\"",
576 "",
577 "",
578 {
580 "locked",
581 "Information about locked memory manager",
582 {
583 {RPCResult::Type::NUM, "used", "Number of bytes used"},
584 {RPCResult::Type::NUM, "free",
585 "Number of bytes available in current arenas"},
586 {RPCResult::Type::NUM, "total",
587 "Total number of bytes managed"},
588 {RPCResult::Type::NUM, "locked",
589 "Amount of bytes that succeeded locking. If this "
590 "number is smaller than total, locking pages failed "
591 "at some point and key data could be swapped to "
592 "disk."},
593 {RPCResult::Type::NUM, "chunks_used",
594 "Number allocated chunks"},
595 {RPCResult::Type::NUM, "chunks_free",
596 "Number unused chunks"},
597 }},
598 }},
599 RPCResult{"mode \"mallocinfo\"", RPCResult::Type::STR, "",
600 "\"<malloc version=\"1\">...\""},
601 },
602 RPCExamples{HelpExampleCli("getmemoryinfo", "") +
603 HelpExampleRpc("getmemoryinfo", "")},
604 [&](const RPCHelpMan &self, const Config &config,
605 const JSONRPCRequest &request) -> UniValue {
606 std::string mode = request.params[0].isNull()
607 ? "stats"
608 : request.params[0].get_str();
609 if (mode == "stats") {
611 obj.pushKV("locked", RPCLockedMemoryInfo());
612 return obj;
613 } else if (mode == "mallocinfo") {
614#ifdef HAVE_MALLOC_INFO
615 return RPCMallocInfo();
616#else
618 "mallocinfo is only available when compiled "
619 "with glibc 2.10+");
620#endif
621 } else {
623 "unknown mode " + mode);
624 }
625 },
626 };
627}
628
629static void EnableOrDisableLogCategories(UniValue cats, bool enable) {
630 cats = cats.get_array();
631 for (size_t i = 0; i < cats.size(); ++i) {
632 std::string cat = cats[i].get_str();
633
634 bool success;
635 if (enable) {
636 success = LogInstance().EnableCategory(cat);
637 } else {
638 success = LogInstance().DisableCategory(cat);
639 }
640
641 if (!success) {
643 "unknown logging category " + cat);
644 }
645 }
646}
647
649 return RPCHelpMan{
650 "logging",
651 "Gets and sets the logging configuration.\n"
652 "When called without an argument, returns the list of categories with "
653 "status that are currently being debug logged or not.\n"
654 "When called with arguments, adds or removes categories from debug "
655 "logging and return the lists above.\n"
656 "The arguments are evaluated in order \"include\", \"exclude\".\n"
657 "If an item is both included and excluded, it will thus end up being "
658 "excluded.\n"
659 "The valid logging categories are: " +
661 "\n"
662 "In addition, the following are available as category names with "
663 "special meanings:\n"
664 " - \"all\", \"1\" : represent all logging categories.\n"
665 " - \"none\", \"0\" : even if other logging categories are "
666 "specified, ignore all of them.\n",
667 {
668 {"include",
671 "The categories to add to debug logging",
672 {
673 {"include_category", RPCArg::Type::STR,
674 RPCArg::Optional::OMITTED, "the valid logging category"},
675 }},
676 {"exclude",
679 "The categories to remove from debug logging",
680 {
681 {"exclude_category", RPCArg::Type::STR,
682 RPCArg::Optional::OMITTED, "the valid logging category"},
683 }},
684 },
685 RPCResult{
687 "",
688 "keys are the logging categories, and values indicates its status",
689 {
690 {RPCResult::Type::BOOL, "category",
691 "if being debug logged or not. false:inactive, true:active"},
692 }},
694 HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"") +
695 HelpExampleRpc("logging", "[\"all\"], [\"libevent\"]")},
696 [&](const RPCHelpMan &self, const Config &config,
697 const JSONRPCRequest &request) -> UniValue {
698 uint32_t original_log_categories = LogInstance().GetCategoryMask();
699 if (request.params[0].isArray()) {
700 EnableOrDisableLogCategories(request.params[0], true);
701 }
702
703 if (request.params[1].isArray()) {
704 EnableOrDisableLogCategories(request.params[1], false);
705 }
706
707 uint32_t updated_log_categories = LogInstance().GetCategoryMask();
708 uint32_t changed_log_categories =
709 original_log_categories ^ updated_log_categories;
710
711 // Update libevent logging if BCLog::LIBEVENT has changed.
712 if (changed_log_categories & BCLog::LIBEVENT) {
714 LogInstance().WillLogCategory(BCLog::LIBEVENT));
715 }
716
717 UniValue result(UniValue::VOBJ);
718 for (const auto &logCatActive : LogInstance().LogCategoriesList()) {
719 result.pushKV(logCatActive.category, logCatActive.active);
720 }
721
722 return result;
723 },
724 };
725}
726
727static RPCHelpMan echo(const std::string &name) {
728 return RPCHelpMan{
729 name,
730 "Simply echo back the input arguments. This command is for "
731 "testing.\n"
732 "\nIt will return an internal bug report when "
733 "arg9='trigger_internal_bug' is passed.\n"
734 "\nThe difference between echo and echojson is that echojson has "
735 "argument conversion enabled in the client-side table in "
736 "bitcoin-cli and the GUI. There is no server-side difference.",
737 {
758 },
759 RPCResult{RPCResult::Type::ANY, "", "Returns whatever was passed in"},
760 RPCExamples{""},
761 [&](const RPCHelpMan &self, const Config &config,
762 const JSONRPCRequest &request) -> UniValue {
763 if (request.params[9].isStr()) {
764 CHECK_NONFATAL(request.params[9].get_str() !=
765 "trigger_internal_bug");
766 }
767
768 return request.params;
769 },
770 };
771}
772
773static RPCHelpMan echo() {
774 return echo("echo");
775}
777 return echo("echojson");
778}
779
781 return RPCHelpMan{
782 "getcurrencyinfo",
783 "Returns an object containing information about the currency.\n",
784 {},
785 {
786 RPCResult{
788 "",
789 "",
790 {
791 {RPCResult::Type::STR, "ticker", "Ticker symbol"},
792 {RPCResult::Type::NUM, "satoshisperunit",
793 "Number of satoshis per base unit"},
794 {RPCResult::Type::NUM, "decimals",
795 "Number of digits to the right of the decimal point."},
796 }},
797 },
798 RPCExamples{HelpExampleCli("getcurrencyinfo", "") +
799 HelpExampleRpc("getcurrencyinfo", "")},
800 [&](const RPCHelpMan &self, const Config &config,
801 const JSONRPCRequest &request) -> UniValue {
802 const Currency &currency = Currency::get();
803
805 res.pushKV("ticker", currency.ticker);
806 res.pushKV("satoshisperunit", currency.baseunit / SATOSHI);
807 res.pushKV("decimals", currency.decimals);
808 return res;
809 },
810 };
811}
812
813static UniValue SummaryToJSON(const IndexSummary &&summary,
814 std::string index_name) {
815 UniValue ret_summary(UniValue::VOBJ);
816 if (!index_name.empty() && index_name != summary.name) {
817 return ret_summary;
818 }
819
821 entry.pushKV("synced", summary.synced);
822 entry.pushKV("best_block_height", summary.best_block_height);
823 ret_summary.pushKV(summary.name, std::move(entry));
824 return ret_summary;
825}
826
828 return RPCHelpMan{
829 "getindexinfo",
830 "Returns the status of one or all available indices currently "
831 "running in the node.\n",
832 {
834 "Filter results for an index with a specific name."},
835 },
836 RPCResult{
838 "",
839 "",
840 {
842 "name",
843 "The name of the index",
844 {
845 {RPCResult::Type::BOOL, "synced",
846 "Whether the index is synced or not"},
847 {RPCResult::Type::NUM, "best_block_height",
848 "The block height to which the index is synced"},
849 }},
850 },
851 },
852 RPCExamples{HelpExampleCli("getindexinfo", "") +
853 HelpExampleRpc("getindexinfo", "") +
854 HelpExampleCli("getindexinfo", "txindex") +
855 HelpExampleRpc("getindexinfo", "txindex")},
856 [&](const RPCHelpMan &self, const Config &config,
857 const JSONRPCRequest &request) -> UniValue {
858 UniValue result(UniValue::VOBJ);
859 const std::string index_name =
860 request.params[0].isNull() ? "" : request.params[0].get_str();
861
862 if (g_txindex) {
863 result.pushKVs(
864 SummaryToJSON(g_txindex->GetSummary(), index_name));
865 }
866
867 if (g_coin_stats_index) {
868 result.pushKVs(SummaryToJSON(g_coin_stats_index->GetSummary(),
869 index_name));
870 }
871
872 ForEachBlockFilterIndex([&result, &index_name](
873 const BlockFilterIndex &index) {
874 result.pushKVs(SummaryToJSON(index.GetSummary(), index_name));
875 });
876
877 return result;
878 },
879 };
880}
881
883 return RPCHelpMan{
884 "gettime",
885 "Returns the node time information\n",
886 {},
887 RPCResult{
889 "time",
890 "",
891 {
892 {RPCResult::Type::NUM, "local", "The node local timestamp"},
893 {RPCResult::Type::NUM, "offset",
894 "The time offset gathered from the other nodes on the "
895 "network"},
896 {RPCResult::Type::NUM, "adjusted",
897 "The adjusted timestamp of this node"},
898 },
899 },
900 RPCExamples{HelpExampleCli("gettime", "") +
901 HelpExampleRpc("gettime", "")},
902 [&](const RPCHelpMan &self, const Config &config,
903 const JSONRPCRequest &request) -> UniValue {
904 UniValue timeObj(UniValue::VOBJ);
905 timeObj.pushKV("local", GetTime());
906 timeObj.pushKV("offset", GetTimeOffset());
907 timeObj.pushKV("adjusted", TicksSinceEpoch<std::chrono::seconds>(
908 GetAdjustedTime()));
909 return timeObj;
910 },
911 };
912}
913
915 return RPCHelpMan{
916 "getinfo",
917 "Returns basic information about the node\n",
918 {},
919 RPCResult{
921 "info",
922 "",
923 {
924 {RPCResult::Type::STR_HEX, "version_number",
925 "The version number"},
926 {RPCResult::Type::STR, "version_full",
927 "The full version as a string"},
928 {RPCResult::Type::BOOL, "avalanche",
929 "Whether avalanche is enabled"},
930 {RPCResult::Type::BOOL, "avalanche_staking_rewards",
931 "Whether avalanche staking rewards is enabled"},
932 {RPCResult::Type::BOOL, "avalanche_staking_preconsensus",
933 "Whether avalanche staking rewards preconsensus is enabled"},
934 {RPCResult::Type::BOOL, "avalanche_preconsensus",
935 "Whether avalanche preconsensus is enabled"},
936 {RPCResult::Type::BOOL, "avalanche_mining_preconsensus",
937 "Whether mining based on avalanche preconsensus is enabled"},
938 },
939 },
940 RPCExamples{HelpExampleCli("getinfo", "") +
941 HelpExampleRpc("getinfo", "")},
942 [&](const RPCHelpMan &self, const Config &config,
943 const JSONRPCRequest &request) -> UniValue {
944 NodeContext &node = EnsureAnyNodeContext(request.context);
946 ArgsManager &argsman = EnsureArgsman(node);
947
948 const Consensus::Params &params =
949 config.GetChainParams().GetConsensus();
950 const CBlockIndex *tip =
951 WITH_LOCK(cs_main, return chainman.ActiveTip());
952
953 UniValue infoObj(UniValue::VOBJ);
954 infoObj.pushKV("version_number", CLIENT_VERSION);
955 infoObj.pushKV("version_full", FormatFullVersion());
956
957 if (node.avalanche) {
958 infoObj.pushKV("avalanche", true);
959 infoObj.pushKV("avalanche_staking_rewards",
960 IsStakingRewardsActivated(params, tip));
961 infoObj.pushKV(
962 "avalanche_staking_preconsensus",
963 node.avalanche->isStakingPreconsensusActivated(tip));
964 const bool fPreconsensus =
965 node.avalanche->isPreconsensusActivated(tip);
966 infoObj.pushKV("avalanche_preconsensus", fPreconsensus);
967 infoObj.pushKV("avalanche_mining_preconsensus",
968 fPreconsensus &&
969 argsman.GetBoolArg(
970 "-avalanchepreconsensusmining",
972 } else {
973 infoObj.pushKV("avalanche", false);
974 infoObj.pushKV("avalanche_staking_rewards", false);
975 infoObj.pushKV("avalanche_staking_preconsensus", false);
976 infoObj.pushKV("avalanche_preconsensus", false);
977 infoObj.pushKV("avalanche_mining_preconsensus", false);
978 }
979 return infoObj;
980 },
981 };
982}
983
985 // clang-format off
986 static const CRPCCommand commands[] = {
987 // category actor (function)
988 // ------------------ ----------------------
989 { "control", getmemoryinfo, },
990 { "control", logging, },
991 { "util", validateaddress, },
992 { "util", createmultisig, },
993 { "util", deriveaddresses, },
994 { "util", getdescriptorinfo, },
995 { "util", verifymessage, },
996 { "util", signmessagewithprivkey, },
997 { "util", getcurrencyinfo, },
998 { "util", getindexinfo, },
999 { "util", gettime, },
1000 { "util", getinfo, },
1001
1002 /* Not shown in help */
1003 { "hidden", setmocktime, },
1004 { "hidden", mockscheduler, },
1005 { "hidden", echo, },
1006 { "hidden", echojson, },
1007 };
1008 // clang-format on
1009 for (const auto &c : commands) {
1010 t.appendCommand(c.name, &c);
1011 }
1012}
static constexpr Amount SATOSHI
Definition: amount.h:148
static constexpr bool DEFAULT_AVALANCHE_MINING_PRECONSENSUS
Default for -avalanchepreconsensusmining.
Definition: avalanche.h:72
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:525
void DisableCategory(LogFlags category)
Definition: logging.cpp:587
void EnableCategory(LogFlags category)
Definition: logging.cpp:574
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:328
Provides an interface for creating and interacting with one or two chainstates: an IBD chainstate gen...
Definition: validation.h:1186
CBlockIndex * ActiveTip() const EXCLUSIVE_LOCKS_REQUIRED(GetMutex())
Definition: validation.h:1444
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:410
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.
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:533
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:25
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:648
static RPCHelpMan setmocktime()
Definition: misc.cpp:448
void RegisterMiscRPCCommands(CRPCTable &t)
Definition: misc.cpp:984
static RPCHelpMan getinfo()
Definition: misc.cpp:914
static void EnableOrDisableLogCategories(UniValue cats, bool enable)
Definition: misc.cpp:629
static UniValue RPCLockedMemoryInfo()
Definition: misc.cpp:527
static RPCHelpMan mockscheduler()
Definition: misc.cpp:492
static RPCHelpMan getmemoryinfo()
Definition: misc.cpp:557
static RPCHelpMan getcurrencyinfo()
Definition: misc.cpp:780
static RPCHelpMan getdescriptorinfo()
Definition: misc.cpp:187
static RPCHelpMan echo(const std::string &name)
Definition: misc.cpp:727
static UniValue SummaryToJSON(const IndexSummary &&summary, std::string index_name)
Definition: misc.cpp:813
static RPCHelpMan gettime()
Definition: misc.cpp:882
static RPCHelpMan echojson()
Definition: misc.cpp:776
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:827
@ LIBEVENT
Definition: logging.h:86
static bool isNull(const AnyVoteItem &item)
Definition: processor.cpp:417
Definition: init.h:31
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:1345
std::string HelpExampleCli(const std::string &methodname, const std::string &args)
Definition: util.cpp:153
CTxDestination AddAndGetMultisigDestination(const int required, const std::vector< CPubKey > &pubkeys, OutputType type, FillableSigningProvider &keystore, CScript &script_out)
Definition: util.cpp:236
const std::string EXAMPLE_ADDRESS
Example CashAddr address used in multiple RPCExamples.
Definition: util.cpp:26
std::string HelpExampleRpc(const std::string &methodname, const std::string &args)
Definition: util.cpp:170
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:25
CPubKey HexToPubKey(const std::string &hex_in)
Definition: util.cpp:194
UniValue DescribeAddress(const CTxDestination &dest)
Definition: util.cpp:304
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
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:140
@ 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:105
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:17
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.