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