LCOV - code coverage report
Current view: top level - src/rpc - node.cpp (source / functions) Hit Total Coverage
Test: fuzz_coverage.info Lines: 198 248 79.8 %
Date: 2023-10-05 15:40:34 Functions: 23 28 82.1 %
Branches: 373 838 44.5 %

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

Generated by: LCOV version 1.14