LCOV - code coverage report
Current view: top level - src/rpc - misc.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 572 599 95.5 %
Date: 2021-06-29 14:35:33 Functions: 33 34 97.1 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 98 120 81.7 %

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

Generated by: LCOV version 1.14