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