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