rpc: add getchainstates

Co-authored-by: Ryan Ofsky <ryan@ofsky.org>
This commit is contained in:
James O'Beirne 2019-03-29 17:55:08 -04:00 committed by James O'Beirne
parent bb05857794
commit 0f64bac603
3 changed files with 77 additions and 0 deletions

View file

@ -24,3 +24,5 @@ are always checked by hash.
You can find more information on this process in the `assumeutxo` design
document (<https://github.com/bitcoin/bitcoin/blob/master/doc/design/assumeutxo.md>).
`getchainstates` has been added to aid in monitoring the assumeutxo sync process.

View file

@ -2799,6 +2799,79 @@ static RPCHelpMan loadtxoutset()
};
}
const std::vector<RPCResult> RPCHelpForChainstate{
{RPCResult::Type::NUM, "blocks", "number of blocks in this chainstate"},
{RPCResult::Type::STR_HEX, "bestblockhash", "blockhash of the tip"},
{RPCResult::Type::NUM, "difficulty", "difficulty of the tip"},
{RPCResult::Type::NUM, "verificationprogress", "progress towards the network tip"},
{RPCResult::Type::STR_HEX, "snapshot_blockhash", /*optional=*/true, "the base block of the snapshot this chainstate is based on, if any"},
{RPCResult::Type::NUM, "coins_db_cache_bytes", "size of the coinsdb cache"},
{RPCResult::Type::NUM, "coins_tip_cache_bytes", "size of the coinstip cache"},
};
static RPCHelpMan getchainstates()
{
return RPCHelpMan{
"getchainstates",
"\nReturn information about chainstates.\n",
{},
RPCResult{
RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::NUM, "headers", "the number of headers seen so far"},
{RPCResult::Type::OBJ, "normal", /*optional=*/true, "fully validated chainstate containing blocks this node has validated starting from the genesis block", RPCHelpForChainstate},
{RPCResult::Type::OBJ, "snapshot", /*optional=*/true, "only present if an assumeutxo snapshot is loaded. Partially validated chainstate containing blocks this node has validated starting from the snapshot. After the snapshot is validated (when the 'normal' chainstate advances far enough to validate it), this chainstate will replace and become the 'normal' chainstate.", RPCHelpForChainstate},
}
},
RPCExamples{
HelpExampleCli("getchainstates", "")
+ HelpExampleRpc("getchainstates", "")
},
[&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue
{
LOCK(cs_main);
UniValue obj(UniValue::VOBJ);
NodeContext& node = EnsureAnyNodeContext(request.context);
ChainstateManager& chainman = *node.chainman;
auto make_chain_data = [&](const Chainstate& cs) EXCLUSIVE_LOCKS_REQUIRED(::cs_main) {
AssertLockHeld(::cs_main);
UniValue data(UniValue::VOBJ);
if (!cs.m_chain.Tip()) {
return data;
}
const CChain& chain = cs.m_chain;
const CBlockIndex* tip = chain.Tip();
data.pushKV("blocks", (int)chain.Height());
data.pushKV("bestblockhash", tip->GetBlockHash().GetHex());
data.pushKV("difficulty", (double)GetDifficulty(tip));
data.pushKV("verificationprogress", GuessVerificationProgress(Params().TxData(), tip));
data.pushKV("coins_db_cache_bytes", cs.m_coinsdb_cache_size_bytes);
data.pushKV("coins_tip_cache_bytes", cs.m_coinstip_cache_size_bytes);
if (cs.m_from_snapshot_blockhash) {
data.pushKV("snapshot_blockhash", cs.m_from_snapshot_blockhash->ToString());
}
return data;
};
if (chainman.GetAll().size() > 1) {
for (Chainstate* chainstate : chainman.GetAll()) {
obj.pushKV(
chainstate->m_from_snapshot_blockhash ? "snapshot" : "normal",
make_chain_data(*chainstate));
}
} else {
obj.pushKV("normal", make_chain_data(chainman.ActiveChainstate()));
}
obj.pushKV("headers", chainman.m_best_header ? chainman.m_best_header->nHeight : -1);
return obj;
}
};
}
void RegisterBlockchainRPCCommands(CRPCTable& t)
{
static const CRPCCommand commands[]{
@ -2824,6 +2897,7 @@ void RegisterBlockchainRPCCommands(CRPCTable& t)
{"blockchain", &getblockfilter},
{"blockchain", &dumptxoutset},
{"blockchain", &loadtxoutset},
{"blockchain", &getchainstates},
{"hidden", &invalidateblock},
{"hidden", &reconsiderblock},
{"hidden", &waitfornewblock},

View file

@ -123,6 +123,7 @@ const std::vector<std::string> RPC_COMMANDS_SAFE_FOR_FUZZING{
"getblockstats",
"getblocktemplate",
"getchaintips",
"getchainstates",
"getchaintxstats",
"getconnectioncount",
"getdeploymentinfo",