Skip to content

Commit

Permalink
Merge branch 'add_rpc_getindexinfo' into 'master'
Browse files Browse the repository at this point in the history
Add `getindexinfo` RPC

Closes Bitcoin-ABC#533

See merge request bitcoin-cash-node/bitcoin-cash-node!1896
  • Loading branch information
dagurval committed Nov 24, 2024
2 parents dea3fb7 + baa4707 commit eac3c98
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 2 deletions.
4 changes: 3 additions & 1 deletion doc/release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ this change in requirements will have minimal to zero impact on our users, most

## New RPC methods

TODO
- The `getindexinfo` RPC returns the actively running indices of the node,
including their current sync status and height. It also accepts an `index_name`
to specify returning only the status of that index.

## User interface changes

Expand Down
15 changes: 15 additions & 0 deletions src/index/base.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,3 +299,18 @@ void BaseIndex::Stop() {
m_thread_sync.join();
}
}

IndexSummary BaseIndex::GetSummary() const {
IndexSummary summary{};
summary.name = GetName();
summary.synced = m_synced.load();
const CBlockIndex *pindex = m_best_block_index.load();
if (!pindex) {
WITH_LOCK(cs_main, pindex = ::ChainActive().Genesis()); // grab genesis (height 0) as default
}
if (pindex) { // this should always be non-nullptr normally, but guard against it being nullptr for safety.
summary.best_block_height = pindex->nHeight;
summary.best_block_hash = pindex->GetBlockHash();
}
return summary;
}
13 changes: 12 additions & 1 deletion src/index/base.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Copyright (c) 2017-2018 The Bitcoin Core developers
// Copyright (c) 2019-2021 The Bitcoin developers
// Copyright (c) 2019-2024 The Bitcoin developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

Expand All @@ -14,6 +14,14 @@

class CBlockIndex;

/** Result type returned by BaseIndex::GetSummary() */
struct IndexSummary {
std::string name;
bool synced{false};
int best_block_height{0};
uint256 best_block_hash;
};

/**
* Base class for indices of blockchain data. This implements
* CValidationInterface and ensures blocks are indexed sequentially according
Expand Down Expand Up @@ -108,4 +116,7 @@ class BaseIndex : public CValidationInterface {

/// Stops the instance from staying in sync with blockchain updates.
void Stop();

/// Get a summary of the index and its state.
IndexSummary GetSummary() const;
};
58 changes: 58 additions & 0 deletions src/rpc/misc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <config.h>
#include <core_io.h>
#include <httpserver.h>
#include <index/txindex.h>
#include <key_io.h>
#include <logging.h>
#include <net.h>
Expand All @@ -26,6 +27,7 @@
#include <univalue.h>

#include <cstdint>
#include <utility>
#ifdef HAVE_MALLOC_INFO
#include <malloc.h>
#endif
Expand Down Expand Up @@ -534,6 +536,61 @@ static UniValue getinfo_deprecated(const Config &config,
"format these in the old format.");
}

static UniValue getindexinfo(const Config &, const JSONRPCRequest &request) {
if (request.fHelp || request.params.size() > 1) {
throw std::runtime_error(
RPCHelpMan{
"getindexinfo",
"\nReturns the status of one or all available indices currently running in the node.\n",
{
{"index_name", RPCArg::Type::STR, /* optional */ true, /* default */ "", "Filter results for an index with a specific name."},
},
RPCResult{
"{ (json object)\n"
" \"name\" : { (json object) The name of the index\n"
" \"synced\" : true|false, (boolean) Whether the index is synced or not\n"
" \"best_block_height\" : n (numeric) The block height to which the index is synced\n"
" },\n"
" ...\n"
"}\n"
},
RPCExamples{
HelpExampleCli("getindexinfo", "")
+ HelpExampleRpc("getindexinfo", "")
+ HelpExampleCli("getindexinfo", "txindex")
+ HelpExampleRpc("getindexinfo", "\"txindex\"")
}
}.ToStringWithResultsAndExamples()
);
}

UniValue::Object result;
const std::string index_name = request.params[0].isNull() ? "" : request.params[0].get_str();

auto SummaryToJSON = [&index_name](const IndexSummary &summary) {
UniValue::Object ret_summary;
if (index_name.empty() || index_name == summary.name) {
UniValue::Object entry;
entry.reserve(2);
entry.emplace_back("synced", summary.synced);
entry.emplace_back("best_block_height", summary.best_block_height);
ret_summary.emplace_back(summary.name, std::move(entry));
}
return ret_summary;
};

auto ExtendResult = [&result](UniValue::Object &&obj) {
for (auto &&kvpair : obj) {
result.emplace_back(std::move(kvpair));
}
};

if (g_txindex) {
ExtendResult(SummaryToJSON(g_txindex->GetSummary()));
}

return result;
}
// clang-format off
static const ContextFreeRPCCommand commands[] = {
// category name actor (function) argNames
Expand All @@ -544,6 +601,7 @@ static const ContextFreeRPCCommand commands[] = {
{ "util", "createmultisig", createmultisig, {"nrequired","keys"} },
{ "util", "verifymessage", verifymessage, {"address","signature","message"} },
{ "util", "signmessagewithprivkey", signmessagewithprivkey, {"privkey","message"} },
{ "util", "getindexinfo", getindexinfo, {"index_name"} },
/* Not shown in help */
{ "hidden", "setmocktime", setmocktime, {"timestamp"}},
{ "hidden", "echo", echo, {"arg0","arg1","arg2","arg3","arg4","arg5","arg6","arg7","arg8","arg9"}},
Expand Down
21 changes: 21 additions & 0 deletions test/functional/rpc_misc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#!/usr/bin/env python3
# Copyright (c) 2019 The Bitcoin Core developers
# Copyright (c) 2024 The Bitcoin developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test RPC misc output."""
Expand All @@ -11,6 +12,7 @@
assert_equal,
assert_greater_than,
assert_greater_than_or_equal,
wait_until,
)

from test_framework.authproxy import JSONRPCException
Expand Down Expand Up @@ -56,6 +58,25 @@ def run_test(self):
node.logging(include=['qt'])
assert_equal(node.logging()['qt'], True)

self.log.info("test getindexinfo")
# Without any indices running the RPC returns an empty object
assert_equal(node.getindexinfo(), {})

# Restart the node with indices and wait for them to sync
self.restart_node(0, ["-txindex"])
wait_until(lambda: all(i["synced"] for i in node.getindexinfo().values()))

# Returns a list of all running indices by default
assert_equal(node.getindexinfo(),
{"txindex": {"synced": True, "best_block_height": 200}})

# Specifying an index by name returns only the status of that index
assert_equal(node.getindexinfo("txindex"),
{"txindex": {"synced": True, "best_block_height": 200}})

# Specifying an unknown index name returns an empty result
assert_equal(node.getindexinfo("foo"), {})


if __name__ == '__main__':
RpcMiscTest().main()

0 comments on commit eac3c98

Please sign in to comment.