Bitcoin ABC 0.32.4
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 <common/args.h>
10#include <config.h>
11#include <consensus/amount.h>
12#include <httpserver.h>
15#include <index/txindex.h>
16#include <interfaces/chain.h>
17#include <key_io.h>
18#include <logging.h>
19#include <node/context.h>
20#include <outputtype.h>
22#include <rpc/blockchain.h>
23#include <rpc/server.h>
24#include <rpc/server_util.h>
25#include <rpc/util.h>
26#include <scheduler.h>
27#include <script/descriptor.h>
28#include <timedata.h>
29#include <util/any.h>
30#include <util/check.h>
31#include <util/message.h> // For MessageSign(), MessageVerify()
32#include <util/strencodings.h>
33#include <util/time.h>
34
35#include <univalue.h>
36
37#include <cstdint>
38#include <tuple>
39#ifdef HAVE_MALLOC_INFO
40#include <malloc.h>
41#endif
42
44
46 return RPCHelpMan{
47 "validateaddress",
48 "Return information about the given bitcoin address.\n",
49 {
51 "The bitcoin address to validate"},
52 },
55 "",
56 "",
57 {
58 {RPCResult::Type::BOOL, "isvalid",
59 "If the address is valid or not. If not, this is the only "
60 "property returned."},
61 {RPCResult::Type::STR, "address",
62 "The bitcoin address validated"},
63 {RPCResult::Type::STR_HEX, "scriptPubKey",
64 "The hex-encoded scriptPubKey generated by the address"},
65 {RPCResult::Type::BOOL, "isscript", "If the key is a script"},
66 }},
67 RPCExamples{HelpExampleCli("validateaddress", EXAMPLE_ADDRESS) +
68 HelpExampleRpc("validateaddress", EXAMPLE_ADDRESS)},
69 [&](const RPCHelpMan &self, const Config &config,
70 const JSONRPCRequest &request) -> UniValue {
71 CTxDestination dest = DecodeDestination(request.params[0].get_str(),
72 config.GetChainParams());
73 bool isValid = IsValidDestination(dest);
74
76 ret.pushKV("isvalid", isValid);
77
78 if (isValid) {
79 if (ret["address"].isNull()) {
80 std::string currentAddress =
81 EncodeDestination(dest, config);
82 ret.pushKV("address", currentAddress);
83
84 CScript scriptPubKey = GetScriptForDestination(dest);
85 ret.pushKV("scriptPubKey", HexStr(scriptPubKey));
86
87 UniValue detail = DescribeAddress(dest);
88 ret.pushKVs(detail);
89 }
90 }
91 return ret;
92 },
93 };
94}
95
97 return RPCHelpMan{
98 "createmultisig",
99 "Creates a multi-signature address with n signature of m keys "
100 "required.\n"
101 "It returns a json object with the address and redeemScript.\n",
102 {
104 "The number of required signatures out of the n keys."},
105 {"keys",
108 "The hex-encoded public keys.",
109 {
111 "The hex-encoded public key"},
112 }},
113 },
114 RPCResult{
116 "",
117 "",
118 {
119 {RPCResult::Type::STR, "address",
120 "The value of the new multisig address."},
121 {RPCResult::Type::STR_HEX, "redeemScript",
122 "The string value of the hex-encoded redemption script."},
123 {RPCResult::Type::STR, "descriptor",
124 "The descriptor for this multisig"},
125 }},
127 "\nCreate a multisig address from 2 public keys\n" +
128 HelpExampleCli("createmultisig",
129 "2 "
130 "\"["
131 "\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd3"
132 "42cf11ae157a7ace5fd\\\","
133 "\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e1"
134 "7e107ef3f6aa5a61626\\\"]\"") +
135 "\nAs a JSON-RPC call\n" +
136 HelpExampleRpc("createmultisig",
137 "2, "
138 "\"["
139 "\\\"03789ed0bb717d88f7d321a368d905e7430207ebbd82bd3"
140 "42cf11ae157a7ace5fd\\\","
141 "\\\"03dbc6764b8884a92e871274b87583e6d5c2a58819473e1"
142 "7e107ef3f6aa5a61626\\\"]\"")},
143 [&](const RPCHelpMan &self, const Config &config,
144 const JSONRPCRequest &request) -> UniValue {
145 int required = request.params[0].getInt<int>();
146
147 // Get the public keys
148 const UniValue &keys = request.params[1].get_array();
149 std::vector<CPubKey> pubkeys;
150 for (size_t i = 0; i < keys.size(); ++i) {
151 if ((keys[i].get_str().length() ==
153 keys[i].get_str().length() == 2 * CPubKey::SIZE) &&
154 IsHex(keys[i].get_str())) {
155 pubkeys.push_back(HexToPubKey(keys[i].get_str()));
156 } else {
158 strprintf("Invalid public key: %s\n",
159 keys[i].get_str()));
160 }
161 }
162
163 // Get the output type
164 OutputType output_type = OutputType::LEGACY;
165
166 // Construct using pay-to-script-hash:
168 CScript inner;
170 required, pubkeys, output_type, keystore, inner);
171
172 // Make the descriptor
173 std::unique_ptr<Descriptor> descriptor =
175
176 UniValue result(UniValue::VOBJ);
177 result.pushKV("address", EncodeDestination(dest, config));
178 result.pushKV("redeemScript", HexStr(inner));
179 result.pushKV("descriptor", descriptor->ToString());
180
181 return result;
182 },
183 };
184}
185
187 return RPCHelpMan{
188 "getdescriptorinfo",
189 {"Analyses a descriptor.\n"},
190 {
192 "The descriptor."},
193 },
194 RPCResult{
196 "",
197 "",
198 {
199 {RPCResult::Type::STR, "descriptor",
200 "The descriptor in canonical form, without private keys"},
201 {RPCResult::Type::STR, "checksum",
202 "The checksum for the input descriptor"},
203 {RPCResult::Type::BOOL, "isrange",
204 "Whether the descriptor is ranged"},
205 {RPCResult::Type::BOOL, "issolvable",
206 "Whether the descriptor is solvable"},
207 {RPCResult::Type::BOOL, "hasprivatekeys",
208 "Whether the input descriptor contained at least one private "
209 "key"},
210 }},
211 RPCExamples{"Analyse a descriptor\n" +
212 HelpExampleCli("getdescriptorinfo",
213 "\"pkh([d34db33f/84h/0h/"
214 "0h]"
215 "0279be667ef9dcbbac55a06295Ce870b07029Bfcdb2"
216 "dce28d959f2815b16f81798)\"")},
217 [&](const RPCHelpMan &self, const Config &config,
218 const JSONRPCRequest &request) -> UniValue {
219 FlatSigningProvider provider;
220 std::string error;
221 auto desc = Parse(request.params[0].get_str(), provider, error);
222 if (!desc) {
224 }
225
226 UniValue result(UniValue::VOBJ);
227 result.pushKV("descriptor", desc->ToString());
228 result.pushKV("checksum",
229 GetDescriptorChecksum(request.params[0].get_str()));
230 result.pushKV("isrange", desc->IsRange());
231 result.pushKV("issolvable", desc->IsSolvable());
232 result.pushKV("hasprivatekeys", provider.keys.size() > 0);
233 return result;
234 },
235 };
236}
237
239 return RPCHelpMan{
240 "deriveaddresses",
241 {"Derives one or more addresses corresponding to an output "
242 "descriptor.\n"
243 "Examples of output descriptors are:\n"
244 " pkh(<pubkey>) P2PKH outputs for the given "
245 "pubkey\n"
246 " sh(multi(<n>,<pubkey>,<pubkey>,...)) P2SH-multisig outputs for "
247 "the given threshold and pubkeys\n"
248 " raw(<hex script>) Outputs whose scriptPubKey "
249 "equals the specified hex scripts\n"
250 "\nIn the above, <pubkey> either refers to a fixed public key in "
251 "hexadecimal notation, or to an xpub/xprv optionally followed by one\n"
252 "or more path elements separated by \"/\", where \"h\" represents a "
253 "hardened child key.\n"
254 "For more information on output descriptors, see the documentation in "
255 "the doc/descriptors.md file.\n"},
256 {
258 "The descriptor."},
260 "If a ranged descriptor is used, this specifies the end or the "
261 "range (in [begin,end] notation) to derive."},
262 },
263 RPCResult{
265 "",
266 "",
267 {
268 {RPCResult::Type::STR, "address", "the derived addresses"},
269 }},
270 RPCExamples{"First three pkh receive addresses\n" +
272 "deriveaddresses",
273 "\"pkh([d34db33f/84h/0h/0h]"
274 "xpub6DJ2dNUysrn5Vt36jH2KLBT2i1auw1tTSSomg8P"
275 "hqNiUtx8QX2SvC9nrHu81fT41fvDUnhMjEzQgXnQjKE"
276 "u3oaqMSzhSrHMxyyoEAmUHQbY/0/*)#3vhfv5h5\" \"[0,2]\"")},
277 [&](const RPCHelpMan &self, const Config &config,
278 const JSONRPCRequest &request) -> UniValue {
279 const std::string desc_str = request.params[0].get_str();
280
281 int64_t range_begin = 0;
282 int64_t range_end = 0;
283
284 if (request.params.size() >= 2 && !request.params[1].isNull()) {
285 std::tie(range_begin, range_end) =
286 ParseDescriptorRange(request.params[1]);
287 }
288
289 FlatSigningProvider key_provider;
290 std::string error;
291 auto desc = Parse(desc_str, key_provider, error,
292 /* require_checksum = */ true);
293 if (!desc) {
295 }
296
297 if (!desc->IsRange() && request.params.size() > 1) {
299 "Range should not be specified for an "
300 "un-ranged descriptor");
301 }
302
303 if (desc->IsRange() && request.params.size() == 1) {
304 throw JSONRPCError(
306 "Range must be specified for a ranged descriptor");
307 }
308
309 UniValue addresses(UniValue::VARR);
310
311 for (int i = range_begin; i <= range_end; ++i) {
312 FlatSigningProvider provider;
313 std::vector<CScript> scripts;
314 if (!desc->Expand(i, key_provider, scripts, provider)) {
315 throw JSONRPCError(
317 strprintf("Cannot derive script without private keys"));
318 }
319
320 for (const CScript &script : scripts) {
321 CTxDestination dest;
322 if (!ExtractDestination(script, dest)) {
323 throw JSONRPCError(
325 strprintf("Descriptor does not have a "
326 "corresponding address"));
327 }
328
329 addresses.push_back(EncodeDestination(dest, config));
330 }
331 }
332
333 // This should not be possible, but an assert seems overkill:
334 if (addresses.empty()) {
335 throw JSONRPCError(RPC_MISC_ERROR, "Unexpected empty result");
336 }
337
338 return addresses;
339 },
340 };
341}
342
344 return RPCHelpMan{
345 "verifymessage",
346 "Verify a signed message\n",
347 {
349 "The bitcoin address to use for the signature."},
351 "The signature provided by the signer in base 64 encoding (see "
352 "signmessage)."},
354 "The message that was signed."},
355 },
357 "If the signature is verified or not."},
359 "\nUnlock the wallet for 30 seconds\n" +
360 HelpExampleCli("walletpassphrase", "\"mypassphrase\" 30") +
361 "\nCreate the signature\n" +
363 "signmessage",
364 "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" \"my message\"") +
365 "\nVerify the signature\n" +
366 HelpExampleCli("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
367 "XX\" \"signature\" \"my "
368 "message\"") +
369 "\nAs a JSON-RPC call\n" +
370 HelpExampleRpc("verifymessage", "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4"
371 "XX\", \"signature\", \"my "
372 "message\"")},
373 [&](const RPCHelpMan &self, const Config &config,
374 const JSONRPCRequest &request) -> UniValue {
375 LOCK(cs_main);
376
377 std::string strAddress = self.Arg<std::string>("address");
378 std::string strSign = self.Arg<std::string>("signature");
379 std::string strMessage = self.Arg<std::string>("message");
380
381 switch (MessageVerify(config.GetChainParams(), strAddress, strSign,
382 strMessage)) {
384 throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");
387 "Address does not refer to key");
390 "Malformed base64 encoding");
393 return false;
395 return true;
396 }
397
398 return false;
399 },
400 };
401}
402
404 return RPCHelpMan{
405 "signmessagewithprivkey",
406 "Sign a message with the private key of an address\n",
407 {
409 "The private key to sign the message with."},
411 "The message to create a signature of."},
412 },
413 RPCResult{RPCResult::Type::STR, "signature",
414 "The signature of the message encoded in base 64"},
415 RPCExamples{"\nCreate the signature\n" +
416 HelpExampleCli("signmessagewithprivkey",
417 "\"privkey\" \"my message\"") +
418 "\nVerify the signature\n" +
419 HelpExampleCli("verifymessage",
420 "\"1D1ZrZNe3JUo7ZycKEYQQiQAWd9y54F4XX\" "
421 "\"signature\" \"my message\"") +
422 "\nAs a JSON-RPC call\n" +
423 HelpExampleRpc("signmessagewithprivkey",
424 "\"privkey\", \"my message\"")},
425 [&](const RPCHelpMan &self, const Config &config,
426 const JSONRPCRequest &request) -> UniValue {
427 std::string strPrivkey = request.params[0].get_str();
428 std::string strMessage = request.params[1].get_str();
429
430 CKey key = DecodeSecret(strPrivkey);
431 if (!key.IsValid()) {
433 "Invalid private key");
434 }
435
436 std::string signature;
437
438 if (!MessageSign(key, strMessage, signature)) {
439 throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Sign failed");
440 }
441
442 return signature;
443 },
444 };
445}
446
448 return RPCHelpMan{
449 "setmocktime",
450 "Set the local time to given timestamp (-regtest only)\n",
451 {
453 UNIX_EPOCH_TIME + "\n"
454 "Pass 0 to go back to using the system time."},
455 },
457 RPCExamples{""},
458 [&](const RPCHelpMan &self, const Config &config,
459 const JSONRPCRequest &request) -> UniValue {
460 if (!config.GetChainParams().IsMockableChain()) {
461 throw std::runtime_error(
462 "setmocktime for regression testing (-regtest mode) only");
463 }
464
465 // For now, don't change mocktime if we're in the middle of
466 // validation, as this could have an effect on mempool time-based
467 // eviction, as well as IsInitialBlockDownload().
468 // TODO: figure out the right way to synchronize around mocktime,
469 // and ensure all call sites of GetTime() are accessing this safely.
470 LOCK(cs_main);
471
472 const int64_t time{request.params[0].getInt<int64_t>()};
473 if (time < 0) {
474 throw JSONRPCError(
476 strprintf("Mocktime can not be negative: %s.", time));
477 }
478 SetMockTime(time);
479 auto node_context = util::AnyPtr<NodeContext>(request.context);
480 if (node_context) {
481 for (const auto &chain_client : node_context->chain_clients) {
482 chain_client->setMockTime(time);
483 }
484 }
485
486 return NullUniValue;
487 },
488 };
489}
490
492 return RPCHelpMan{
493 "mockscheduler",
494 "Bump the scheduler into the future (-regtest only)\n",
495 {
497 "Number of seconds to forward the scheduler into the future."},
498 },
500 RPCExamples{""},
501 [&](const RPCHelpMan &self, const Config &config,
502 const JSONRPCRequest &request) -> UniValue {
503 if (!Params().IsMockableChain()) {
504 throw std::runtime_error("mockscheduler is for regression "
505 "testing (-regtest mode) only");
506 }
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, 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:143
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:228
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:647
static RPCHelpMan setmocktime()
Definition: misc.cpp:447
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:491
static RPCHelpMan getmemoryinfo()
Definition: misc.cpp:556
static RPCHelpMan getcurrencyinfo()
Definition: misc.cpp:779
static RPCHelpMan getdescriptorinfo()
Definition: misc.cpp:186
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:238
static RPCHelpMan signmessagewithprivkey()
Definition: misc.cpp:403
static RPCHelpMan createmultisig()
Definition: misc.cpp:96
static RPCHelpMan verifymessage()
Definition: misc.cpp:343
static RPCHelpMan validateaddress()
Definition: misc.cpp:45
static RPCHelpMan getindexinfo()
Definition: misc.cpp:826
@ 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: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
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: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.