LCOV - code coverage report
Current view: top level - src/rpc - node.cpp (source / functions) Coverage Total Hit
Test: total_coverage.info Lines: 95.4 % 241 230
Test Date: 2026-10-09 06:24:36 Functions: 95.7 % 23 22
Branches: 50.4 % 760 383

             Branch data     Line data    Source code
       1                 :             : // Copyright (c) 2010 Satoshi Nakamoto
       2                 :             : // Copyright (c) 2009-present 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 <bitcoin-build-config.h> // IWYU pragma: keep
       7                 :             : 
       8                 :             : #include <rpc/register.h> // IWYU pragma: associated
       9                 :             : 
      10                 :             : #include <chainparams.h>
      11                 :             : #include <index/base.h>
      12                 :             : #include <index/blockfilterindex.h>
      13                 :             : #include <index/coinstatsindex.h>
      14                 :             : #include <index/txindex.h>
      15                 :             : #include <index/txospenderindex.h>
      16                 :             : #include <interfaces/chain.h>
      17                 :             : #include <interfaces/echo.h>
      18                 :             : #include <interfaces/init.h>
      19                 :             : #include <interfaces/ipc.h>
      20                 :             : #include <kernel/cs_main.h>
      21                 :             : #include <logging.h>
      22                 :             : #include <node/context.h>
      23                 :             : #include <rpc/protocol.h>
      24                 :             : #include <rpc/request.h>
      25                 :             : #include <rpc/server.h>
      26                 :             : #include <rpc/server_util.h>
      27                 :             : #include <rpc/util.h>
      28                 :             : #include <scheduler.h>
      29                 :             : #include <support/lockedpool.h>
      30                 :             : #include <sync.h>
      31                 :             : #include <tinyformat.h>
      32                 :             : #include <univalue.h>
      33                 :             : #include <util/check.h>
      34                 :             : #include <util/time.h>
      35                 :             : #include <validationinterface.h>
      36                 :             : 
      37                 :             : #include <cstdint>
      38                 :             : #include <cstdio>
      39                 :             : #include <cstdlib>
      40                 :             : #include <limits>
      41                 :             : #include <memory>
      42                 :             : #include <optional>
      43                 :             : #include <stdexcept>
      44                 :             : #include <string>
      45                 :             : #include <utility>
      46                 :             : #include <vector>
      47                 :             : #ifdef HAVE_MALLOC_INFO
      48                 :             : #include <malloc.h>
      49                 :             : #endif
      50                 :             : #include <string_view>
      51                 :             : 
      52                 :             : using node::NodeContext;
      53                 :             : 
      54                 :        4014 : static RPCMethod setmocktime()
      55                 :             : {
      56                 :        4014 :     return RPCMethod{
      57                 :        4014 :         "setmocktime",
      58         [ +  - ]:        8028 :         "Set the local time to given timestamp (-regtest only)\n",
      59                 :             :         {
      60         [ +  - ]:        8028 :             {"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, UNIX_EPOCH_TIME + "\n"
      61         [ +  - ]:        4014 :              "Pass 0 to go back to using the system time."},
      62                 :             :         },
      63   [ +  -  +  -  :        8028 :         RPCResult{RPCResult::Type::NONE, "", ""},
             +  -  +  - ]
      64   [ +  -  +  - ]:       12042 :         RPCExamples{""},
      65                 :        4014 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
      66                 :             : {
      67         [ -  + ]:        1419 :     if (!Params().IsMockableChain()) {
      68         [ #  # ]:           0 :         throw std::runtime_error("setmocktime is for regression testing (-regtest mode) only");
      69                 :             :     }
      70                 :             : 
      71                 :             :     // For now, don't change mocktime if we're in the middle of validation, as
      72                 :             :     // this could have an effect on mempool time-based eviction, as well as
      73                 :             :     // IsCurrentForFeeEstimation() and IsInitialBlockDownload().
      74                 :             :     // TODO: figure out the right way to synchronize around mocktime, and
      75                 :             :     // ensure all call sites of GetTime() are accessing this safely.
      76                 :        1419 :     LOCK(cs_main);
      77                 :             : 
      78   [ +  -  +  - ]:        1419 :     const int64_t time{request.params[0].getInt<int64_t>()};
      79                 :             :     // block timestamps are uint32_t, so mocking time beyond that is meaningless for anything
      80                 :             :     // consensus-related and can cause integer overflow/truncation issues in time arithmetic.
      81                 :        1419 :     constexpr int64_t max_time{std::numeric_limits<uint32_t>::max()};
      82         [ +  + ]:        1419 :     if (time < 0 || time > max_time) {
      83   [ +  -  +  - ]:           8 :         throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Mocktime must be in the range [0, %s], not %s.", max_time, time));
      84                 :             :     }
      85                 :             : 
      86         [ +  - ]:        1415 :     SetMockTime(std::chrono::seconds{time});
      87         [ +  - ]:        1415 :     const NodeContext& node_context{EnsureAnyNodeContext(request.context)};
      88         [ +  + ]:        1606 :     for (const auto& chain_client : node_context.chain_clients) {
      89         [ +  - ]:         191 :         chain_client->setMockTime(time);
      90                 :             :     }
      91                 :             : 
      92         [ +  - ]:        1415 :     return UniValue::VNULL;
      93                 :        1415 : },
      94   [ +  -  +  -  :       20070 :     };
             +  +  -  - ]
      95         [ +  - ]:        8028 : }
      96                 :             : 
      97                 :        2625 : static RPCMethod mockscheduler()
      98                 :             : {
      99                 :        2625 :     return RPCMethod{
     100                 :        2625 :         "mockscheduler",
     101         [ +  - ]:        5250 :         "Bump the scheduler into the future (-regtest only)\n",
     102                 :             :         {
     103   [ +  -  +  - ]:        5250 :             {"delta_time", RPCArg::Type::NUM, RPCArg::Optional::NO, "Number of seconds to forward the scheduler into the future." },
     104                 :             :         },
     105   [ +  -  +  -  :        5250 :         RPCResult{RPCResult::Type::NONE, "", ""},
             +  -  +  - ]
     106   [ +  -  +  - ]:        7875 :         RPCExamples{""},
     107                 :        2625 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     108                 :             : {
     109         [ -  + ]:          30 :     if (!Params().IsMockableChain()) {
     110         [ #  # ]:           0 :         throw std::runtime_error("mockscheduler is for regression testing (-regtest mode) only");
     111                 :             :     }
     112                 :             : 
     113                 :          30 :     int64_t delta_seconds = request.params[0].getInt<int64_t>();
     114         [ -  + ]:          30 :     if (delta_seconds <= 0 || delta_seconds > 3600) {
     115         [ #  # ]:           0 :         throw std::runtime_error("delta_time must be between 1 and 3600 seconds (1 hr)");
     116                 :             :     }
     117                 :             : 
     118                 :          30 :     const NodeContext& node_context{EnsureAnyNodeContext(request.context)};
     119                 :          30 :     CHECK_NONFATAL(node_context.scheduler)->MockForward(std::chrono::seconds{delta_seconds});
     120                 :          30 :     CHECK_NONFATAL(node_context.validation_signals)->SyncWithValidationInterfaceQueue();
     121         [ +  + ]:          55 :     for (const auto& chain_client : node_context.chain_clients) {
     122                 :          25 :         chain_client->schedulerMockForward(std::chrono::seconds(delta_seconds));
     123                 :             :     }
     124                 :             : 
     125                 :          30 :     return UniValue::VNULL;
     126                 :             : },
     127   [ +  -  +  -  :       13125 :     };
             +  +  -  - ]
     128         [ +  - ]:        5250 : }
     129                 :             : 
     130                 :           1 : static UniValue RPCLockedMemoryInfo()
     131                 :             : {
     132                 :           1 :     LockedPool::Stats stats = LockedPoolManager::Instance().stats();
     133                 :           1 :     UniValue obj(UniValue::VOBJ);
     134   [ +  -  +  -  :           2 :     obj.pushKV("used", stats.used);
                   +  - ]
     135   [ +  -  +  -  :           2 :     obj.pushKV("free", stats.free);
                   +  - ]
     136   [ +  -  +  -  :           2 :     obj.pushKV("total", stats.total);
                   +  - ]
     137   [ +  -  +  -  :           2 :     obj.pushKV("locked", stats.locked);
                   +  - ]
     138   [ +  -  +  -  :           2 :     obj.pushKV("chunks_used", stats.chunks_used);
                   +  - ]
     139   [ +  -  +  -  :           2 :     obj.pushKV("chunks_free", stats.chunks_free);
                   +  - ]
     140                 :           1 :     return obj;
     141                 :           0 : }
     142                 :             : 
     143                 :             : #ifdef HAVE_MALLOC_INFO
     144                 :           1 : static std::string RPCMallocInfo()
     145                 :             : {
     146                 :           1 :     char *ptr = nullptr;
     147                 :           1 :     size_t size = 0;
     148                 :           1 :     FILE *f = open_memstream(&ptr, &size);
     149         [ +  - ]:           1 :     if (f) {
     150                 :           1 :         malloc_info(0, f);
     151                 :           1 :         fclose(f);
     152         [ +  - ]:           1 :         if (ptr) {
     153                 :           1 :             std::string rv(ptr, size);
     154                 :           1 :             free(ptr);
     155                 :           1 :             return rv;
     156                 :             :         }
     157                 :             :     }
     158                 :           0 :     return "";
     159                 :             : }
     160                 :             : #endif
     161                 :             : 
     162                 :        2609 : static RPCMethod getmemoryinfo()
     163                 :             : {
     164                 :             :     /* Please, avoid using the word "pool" here in the RPC interface or help,
     165                 :             :      * as users will undoubtedly confuse it with the other "memory pool"
     166                 :             :      */
     167                 :        2609 :     return RPCMethod{"getmemoryinfo",
     168         [ +  - ]:        5218 :                 "Returns an object containing information about memory usage.\n",
     169                 :             :                 {
     170   [ +  -  +  -  :        7827 :                     {"mode", RPCArg::Type::STR, RPCArg::Default{"stats"}, "determines what kind of information is returned.\n"
                   +  - ]
     171                 :             :             "  - \"stats\" returns general statistics about memory usage in the daemon.\n"
     172                 :             :             "  - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc)."},
     173                 :             :                 },
     174                 :             :                 {
     175         [ +  - ]:        2609 :                     RPCResult{"mode \"stats\"",
     176   [ +  -  +  - ]:        5218 :                         RPCResult::Type::OBJ, "", "",
     177                 :             :                         {
     178   [ +  -  +  - ]:        5218 :                             {RPCResult::Type::OBJ, "locked", "Information about locked memory manager",
     179                 :             :                             {
     180   [ +  -  +  - ]:        5218 :                                 {RPCResult::Type::NUM, "used", "Number of bytes used"},
     181   [ +  -  +  - ]:        5218 :                                 {RPCResult::Type::NUM, "free", "Number of bytes available in current arenas"},
     182   [ +  -  +  - ]:        5218 :                                 {RPCResult::Type::NUM, "total", "Total number of bytes managed"},
     183   [ +  -  +  - ]:        5218 :                                 {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."},
     184   [ +  -  +  - ]:        5218 :                                 {RPCResult::Type::NUM, "chunks_used", "Number allocated chunks"},
     185   [ +  -  +  - ]:        5218 :                                 {RPCResult::Type::NUM, "chunks_free", "Number unused chunks"},
     186                 :             :                             }},
     187                 :             :                         }
     188   [ +  -  +  -  :       44353 :                     },
          +  +  +  +  -  
                -  -  - ]
     189         [ +  - ]:        2609 :                     RPCResult{"mode \"mallocinfo\"",
     190   [ +  -  +  - ]:        5218 :                         RPCResult::Type::STR, "", "\"<malloc version=\"1\">...\""
     191                 :        2609 :                     },
     192                 :             :                 },
     193                 :        2609 :                 RPCExamples{
     194   [ +  -  +  -  :        5218 :                     HelpExampleCli("getmemoryinfo", "")
                   +  - ]
     195   [ +  -  +  -  :       10436 :             + HelpExampleRpc("getmemoryinfo", "")
                   +  - ]
     196         [ +  - ]:        2609 :                 },
     197                 :        2609 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     198                 :             : {
     199                 :           3 :     auto mode{self.Arg<std::string_view>("mode")};
     200         [ +  + ]:           3 :     if (mode == "stats") {
     201                 :           1 :         UniValue obj(UniValue::VOBJ);
     202   [ +  -  +  -  :           1 :         obj.pushKV("locked", RPCLockedMemoryInfo());
                   +  - ]
     203                 :           1 :         return obj;
     204         [ +  + ]:           2 :     } else if (mode == "mallocinfo") {
     205                 :             : #ifdef HAVE_MALLOC_INFO
     206         [ +  - ]:           1 :         return RPCMallocInfo();
     207                 :             : #else
     208                 :             :         throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo mode not available");
     209                 :             : #endif
     210                 :             :     } else {
     211   [ +  -  +  - ]:           2 :         throw JSONRPCError(RPC_INVALID_PARAMETER, tfm::format("unknown mode %s", mode));
     212                 :             :     }
     213                 :             : },
     214   [ +  -  +  -  :       26090 :     };
          +  -  +  -  +  
          +  +  +  -  -  
                   -  - ]
     215   [ +  -  +  -  :       52180 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
             -  -  -  -  
                      - ]
     216                 :             : 
     217                 :           6 : static void EnableOrDisableLogCategories(UniValue cats, bool enable) {
     218                 :           6 :     cats = cats.get_array();
     219   [ -  +  +  + ]:          12 :     for (unsigned int i = 0; i < cats.size(); ++i) {
     220         [ -  + ]:           6 :         std::string cat = cats[i].get_str();
     221                 :             : 
     222                 :           6 :         bool success;
     223         [ +  + ]:           6 :         if (enable) {
     224   [ +  -  -  +  :           4 :             success = LogInstance().EnableCategory(cat);
                   +  - ]
     225                 :             :         } else {
     226   [ +  -  -  +  :           2 :             success = LogInstance().DisableCategory(cat);
                   +  - ]
     227                 :             :         }
     228                 :             : 
     229         [ -  + ]:           6 :         if (!success) {
     230   [ #  #  #  # ]:           0 :             throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat);
     231                 :             :         }
     232                 :           6 :     }
     233                 :           6 : }
     234                 :             : 
     235                 :        2624 : static RPCMethod logging()
     236                 :             : {
     237                 :        2624 :     return RPCMethod{"logging",
     238                 :             :             "Gets and sets the logging configuration.\n"
     239                 :             :             "When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n"
     240                 :             :             "When called with arguments, adds or removes categories from debug logging and return the lists above.\n"
     241                 :             :             "The arguments are evaluated in order \"include\", \"exclude\".\n"
     242                 :             :             "If an item is both included and excluded, it will thus end up being excluded.\n"
     243   [ +  -  +  -  :        5248 :             "The valid logging categories are: " + LogInstance().LogCategoriesString() + "\n"
                   +  - ]
     244                 :             :             "In addition, the following are available as category names with special meanings:\n"
     245                 :        2624 :             "  - \"all\",  \"1\" : represent all logging categories.\n"
     246                 :             :             ,
     247                 :             :                 {
     248   [ +  -  +  - ]:        5248 :                     {"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The categories to add to debug logging",
     249                 :             :                         {
     250   [ +  -  +  - ]:        5248 :                             {"include_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
     251                 :             :                         }},
     252   [ +  -  +  - ]:        5248 :                     {"exclude", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The categories to remove from debug logging",
     253                 :             :                         {
     254   [ +  -  +  - ]:        5248 :                             {"exclude_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},
     255                 :             :                         }},
     256                 :             :                 },
     257         [ +  - ]:        5248 :                 RPCResult{
     258   [ +  -  +  - ]:        5248 :                     RPCResult::Type::OBJ_DYN, "", "keys are the logging categories, and values indicates its status",
     259                 :             :                     {
     260   [ +  -  +  - ]:        5248 :                         {RPCResult::Type::BOOL, "category", "if being debug logged or not. false:inactive, true:active"},
     261                 :             :                     }
     262   [ +  -  +  -  :       10496 :                 },
             +  +  -  - ]
     263                 :        2624 :                 RPCExamples{
     264   [ +  -  +  -  :        5248 :                     HelpExampleCli("logging", "\"[\\\"all\\\"]\" \"[\\\"http\\\"]\"")
                   +  - ]
     265   [ +  -  +  -  :       10496 :             + HelpExampleRpc("logging", "[\"all\"], [\"leveldb\"]")
             +  -  +  - ]
     266         [ +  - ]:        2624 :                 },
     267                 :        2624 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     268                 :             : {
     269         [ +  + ]:          17 :     if (request.params[0].isArray()) {
     270         [ +  - ]:           4 :         EnableOrDisableLogCategories(request.params[0], true);
     271                 :             :     }
     272         [ +  + ]:          17 :     if (request.params[1].isArray()) {
     273         [ +  - ]:           2 :         EnableOrDisableLogCategories(request.params[1], false);
     274                 :             :     }
     275                 :             : 
     276                 :          17 :     UniValue result(UniValue::VOBJ);
     277   [ +  -  +  -  :         527 :     for (const auto& logCatActive : LogInstance().LogCategoriesList()) {
                   +  + ]
     278   [ +  -  -  +  :        1530 :         result.pushKV(logCatActive.category, logCatActive.active);
                   +  - ]
     279                 :          17 :     }
     280                 :             : 
     281                 :          17 :     return result;
     282                 :           0 : },
     283   [ +  -  +  -  :       31488 :     };
          +  -  +  -  +  
          +  +  +  +  +  
          -  -  -  -  -  
                      - ]
     284   [ +  -  +  -  :       26240 : }
          +  -  +  -  +  
                -  -  - ]
     285                 :             : 
     286                 :        5567 : static RPCMethod echo(const std::string& name)
     287                 :             : {
     288         [ -  + ]:        5567 :     return RPCMethod{
     289                 :             :         name,
     290                 :        5567 :         "Simply echo back the input arguments. This command is for testing.\n"
     291                 :             :                 "\nIt will return an internal bug report when arg9='trigger_internal_bug' is passed.\n"
     292                 :             :                 "\nThe difference between echo and echojson is that echojson has argument conversion enabled in the client-side table in "
     293                 :             :                 "bitcoin-cli and the GUI. There is no server-side difference.",
     294                 :             :         {
     295   [ +  -  +  -  :       11134 :             {"arg0", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     296   [ +  -  +  -  :       11134 :             {"arg1", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     297   [ +  -  +  -  :       11134 :             {"arg2", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     298   [ +  -  +  -  :       11134 :             {"arg3", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     299   [ +  -  +  -  :       11134 :             {"arg4", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     300   [ +  -  +  -  :       11134 :             {"arg5", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     301   [ +  -  +  -  :       11134 :             {"arg6", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     302   [ +  -  +  -  :       11134 :             {"arg7", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     303   [ +  -  +  -  :       11134 :             {"arg8", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     304   [ +  -  +  -  :       11134 :             {"arg9", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "", RPCArgOptions{.skip_type_check = true}},
                   +  - ]
     305                 :             :         },
     306   [ +  -  +  -  :       11134 :                 RPCResult{RPCResult::Type::ANY, "", "Returns whatever was passed in"},
             +  -  +  - ]
     307   [ +  -  +  - ]:       16701 :                 RPCExamples{""},
     308                 :        5567 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     309                 :             : {
     310         [ +  + ]:         377 :     if (request.params[9].isStr()) {
     311                 :           1 :         CHECK_NONFATAL(request.params[9].get_str() != "trigger_internal_bug");
     312                 :             :     }
     313                 :             : 
     314                 :         376 :     return request.params;
     315                 :             : },
     316   [ +  -  +  -  :       83505 :     };
          +  -  +  +  -  
                      - ]
     317   [ +  -  +  -  :       55670 : }
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  -  - ]
     318                 :             : 
     319         [ +  - ]:        5932 : static RPCMethod echo() { return echo("echo"); }
     320         [ +  - ]:        5202 : static RPCMethod echojson() { return echo("echojson"); }
     321                 :             : 
     322                 :        2596 : static RPCMethod echoipc()
     323                 :             : {
     324                 :        2596 :     return RPCMethod{
     325                 :        2596 :         "echoipc",
     326         [ +  - ]:        5192 :         "Echo back the input argument, passing it through a spawned process in a multiprocess build.\n"
     327                 :             :         "This command is for testing.\n",
     328   [ +  -  +  - ]:        5192 :         {{"arg", RPCArg::Type::STR, RPCArg::Optional::NO, "The string to echo",}},
     329   [ +  -  +  -  :        5192 :         RPCResult{RPCResult::Type::STR, "echo", "The echoed string."},
             +  -  +  - ]
     330   [ +  -  +  -  :        5192 :         RPCExamples{HelpExampleCli("echo", "\"Hello world\"") +
                   +  - ]
     331   [ +  -  +  -  :       10384 :                     HelpExampleRpc("echo", "\"Hello world\"")},
          +  -  +  -  +  
                      - ]
     332                 :        2596 :         [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue {
     333                 :           1 :             interfaces::Init& local_init = *EnsureAnyNodeContext(request.context).init;
     334                 :           1 :             std::unique_ptr<interfaces::Echo> echo;
     335   [ +  -  -  + ]:           1 :             if (interfaces::Ipc* ipc = local_init.ipc()) {
     336                 :             :                 // Spawn a new bitcoin-node process and call makeEcho to get a
     337                 :             :                 // client pointer to a interfaces::Echo instance running in
     338                 :             :                 // that process. This is just for testing. A slightly more
     339                 :             :                 // realistic test spawning a different executable instead of
     340                 :             :                 // the same executable would add a new bitcoin-echo executable,
     341                 :             :                 // and spawn bitcoin-echo below instead of bitcoin-node. But
     342                 :             :                 // using bitcoin-node avoids the need to build and install a
     343                 :             :                 // new executable just for this one test.
     344         [ #  # ]:           0 :                 auto init = ipc->spawnProcess("bitcoin-node");
     345         [ #  # ]:           0 :                 echo = init->makeEcho();
     346   [ #  #  #  # ]:           0 :                 ipc->addCleanup(*echo, [init = init.release()] { delete init; });
     347                 :           0 :             } else {
     348                 :             :                 // IPC support is not available because this is a bitcoind
     349                 :             :                 // process not a bitcoind-node process, so just create a local
     350                 :             :                 // interfaces::Echo object and return it so the `echoipc` RPC
     351                 :             :                 // method will work, and the python test calling `echoipc`
     352                 :             :                 // can expect the same result.
     353         [ +  - ]:           2 :                 echo = local_init.makeEcho();
     354                 :             :             }
     355   [ +  -  +  -  :           2 :             return echo->echo(request.params[0].get_str());
             +  -  +  - ]
     356                 :           1 :         },
     357   [ +  -  +  -  :       12980 :     };
             +  +  -  - ]
     358         [ +  - ]:        5192 : }
     359                 :             : 
     360                 :         218 : static UniValue SummaryToJSON(const IndexSummary&& summary, std::string index_name)
     361                 :             : {
     362                 :         218 :     UniValue ret_summary(UniValue::VOBJ);
     363   [ +  +  +  + ]:         218 :     if (!index_name.empty() && index_name != summary.name) return ret_summary;
     364                 :             : 
     365                 :         200 :     UniValue entry(UniValue::VOBJ);
     366   [ +  -  +  -  :         400 :     entry.pushKV("synced", summary.synced);
                   +  - ]
     367   [ +  -  +  -  :         400 :     entry.pushKV("best_block_height", summary.best_block_height);
                   +  - ]
     368   [ -  +  +  - ]:         600 :     ret_summary.pushKV(summary.name, std::move(entry));
     369                 :         200 :     return ret_summary;
     370                 :         200 : }
     371                 :             : 
     372                 :        2736 : static RPCMethod getindexinfo()
     373                 :             : {
     374                 :        2736 :     return RPCMethod{
     375                 :        2736 :         "getindexinfo",
     376         [ +  - ]:        5472 :         "Returns the status of one or all available indices currently running in the node.\n",
     377                 :             :                 {
     378   [ +  -  +  - ]:        5472 :                     {"index_name", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "Filter results for an index with a specific name."},
     379                 :             :                 },
     380         [ +  - ]:        5472 :                 RPCResult{
     381   [ +  -  +  - ]:        5472 :                     RPCResult::Type::OBJ_DYN, "", "", {
     382                 :             :                         {
     383   [ +  -  +  - ]:        5472 :                             RPCResult::Type::OBJ, "name", "The name of the index",
     384                 :             :                             {
     385   [ +  -  +  - ]:        5472 :                                 {RPCResult::Type::BOOL, "synced", "Whether the index is synced or not"},
     386   [ +  -  +  - ]:        5472 :                                 {RPCResult::Type::NUM, "best_block_height", "The block height to which the index is synced"},
     387                 :             :                             }
     388                 :             :                         },
     389                 :             :                     },
     390   [ +  -  +  -  :       24624 :                 },
          +  -  +  +  +  
             +  -  -  -  
                      - ]
     391                 :        2736 :                 RPCExamples{
     392   [ +  -  +  -  :        5472 :                     HelpExampleCli("getindexinfo", "")
                   +  - ]
     393   [ +  -  +  -  :       10944 :                   + HelpExampleRpc("getindexinfo", "")
             +  -  +  - ]
     394   [ +  -  +  -  :       10944 :                   + HelpExampleCli("getindexinfo", "txindex")
             +  -  +  - ]
     395   [ +  -  +  -  :       10944 :                   + HelpExampleRpc("getindexinfo", R"("txindex")")
             +  -  +  - ]
     396         [ +  - ]:        2736 :                 },
     397                 :        2736 :                 [](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue
     398                 :             : {
     399                 :         130 :     UniValue result(UniValue::VOBJ);
     400   [ +  -  +  - ]:         130 :     const std::string index_name{self.MaybeArg<std::string_view>("index_name").value_or("")};
     401                 :             : 
     402         [ +  + ]:         130 :     if (g_txindex) {
     403   [ -  +  +  -  :          64 :         result.pushKVs(SummaryToJSON(g_txindex->GetSummary(), index_name));
             +  -  +  - ]
     404                 :             :     }
     405                 :             : 
     406         [ +  + ]:         130 :     if (g_coin_stats_index) {
     407   [ -  +  +  -  :         118 :         result.pushKVs(SummaryToJSON(g_coin_stats_index->GetSummary(), index_name));
             +  -  +  - ]
     408                 :             :     }
     409                 :             : 
     410         [ +  + ]:         130 :     if (g_txospenderindex) {
     411   [ -  +  +  -  :          40 :         result.pushKVs(SummaryToJSON(g_txospenderindex->GetSummary(), index_name));
             +  -  +  - ]
     412                 :             :     }
     413                 :             : 
     414         [ +  - ]:         130 :     ForEachBlockFilterIndex([&result, &index_name](const BlockFilterIndex& index) {
     415   [ -  +  +  -  :         214 :         result.pushKVs(SummaryToJSON(index.GetSummary(), index_name));
             +  -  +  - ]
     416                 :         107 :     });
     417                 :             : 
     418                 :         130 :     return result;
     419                 :         130 : },
     420   [ +  -  +  -  :       13680 :     };
             +  +  -  - ]
     421   [ +  -  +  -  :       21888 : }
          +  -  +  -  -  
                      - ]
     422                 :             : 
     423                 :        1442 : void RegisterNodeRPCCommands(CRPCTable& t)
     424                 :             : {
     425                 :        1442 :     static const CRPCCommand commands[]{
     426         [ +  - ]:        2592 :         {"control", &getmemoryinfo},
     427         [ +  - ]:        2592 :         {"control", &logging},
     428         [ +  - ]:        2592 :         {"util", &getindexinfo},
     429         [ +  - ]:        2592 :         {"hidden", &setmocktime},
     430         [ +  - ]:        2592 :         {"hidden", &mockscheduler},
     431         [ +  - ]:        2592 :         {"hidden", &echo},
     432         [ +  - ]:        2592 :         {"hidden", &echojson},
     433         [ +  - ]:        2592 :         {"hidden", &echoipc},
     434   [ +  +  +  -  :       11810 :     };
          +  -  +  -  +  
          -  +  -  +  -  
          +  -  +  -  +  
                -  -  - ]
     435         [ +  + ]:       12978 :     for (const auto& c : commands) {
     436                 :       11536 :         t.appendCommand(c.name, &c);
     437                 :             :     }
     438                 :        1442 : }
        

Generated by: LCOV version 2.0-1