Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/blockchain.cpp
Show First 20 Lines • Show All 1,292 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
{"hash_or_height", | {"hash_or_height", | ||||
RPCArg::Type::NUM, | RPCArg::Type::NUM, | ||||
RPCArg::Optional::OMITTED, | RPCArg::Optional::OMITTED, | ||||
"The block hash or height of the target height (only available " | "The block hash or height of the target height (only available " | ||||
"with coinstatsindex).", | "with coinstatsindex).", | ||||
"", | "", | ||||
{"", "string or numeric"}}, | {"", "string or numeric"}}, | ||||
}, | }, | ||||
RPCResult{RPCResult::Type::OBJ, | RPCResult{ | ||||
RPCResult::Type::OBJ, | |||||
"", | "", | ||||
"", | "", | ||||
{ | { | ||||
{RPCResult::Type::NUM, "height", | {RPCResult::Type::NUM, "height", | ||||
"The current block height (index)"}, | "The current block height (index)"}, | ||||
{RPCResult::Type::STR_HEX, "bestblock", | {RPCResult::Type::STR_HEX, "bestblock", | ||||
"The hash of the block at the tip of the chain"}, | "The hash of the block at the tip of the chain"}, | ||||
{RPCResult::Type::NUM, "txouts", | {RPCResult::Type::NUM, "txouts", | ||||
"The number of unspent transaction outputs"}, | "The number of unspent transaction outputs"}, | ||||
{RPCResult::Type::NUM, "bogosize", | {RPCResult::Type::NUM, "bogosize", | ||||
"Database-independent, meaningless metric indicating " | "Database-independent, meaningless metric indicating " | ||||
"the UTXO set size"}, | "the UTXO set size"}, | ||||
{RPCResult::Type::STR_HEX, "hash_serialized", | {RPCResult::Type::STR_HEX, "hash_serialized", | ||||
/* optional */ true, | /* optional */ true, | ||||
"The serialized hash (only present if 'hash_serialized' " | "The serialized hash (only present if 'hash_serialized' " | ||||
"hash_type is chosen)"}, | "hash_type is chosen)"}, | ||||
{RPCResult::Type::STR_HEX, "muhash", /* optional */ true, | {RPCResult::Type::STR_HEX, "muhash", /* optional */ true, | ||||
"The serialized hash (only present if 'muhash' " | "The serialized hash (only present if 'muhash' " | ||||
"hash_type is chosen)"}, | "hash_type is chosen)"}, | ||||
{RPCResult::Type::NUM, "transactions", | {RPCResult::Type::NUM, "transactions", | ||||
"The number of transactions with unspent outputs (not " | "The number of transactions with unspent outputs (not " | ||||
"available when coinstatsindex is used)"}, | "available when coinstatsindex is used)"}, | ||||
{RPCResult::Type::NUM, "disk_size", | {RPCResult::Type::NUM, "disk_size", | ||||
"The estimated size of the chainstate on disk (not " | "The estimated size of the chainstate on disk (not " | ||||
"available when coinstatsindex is used)"}, | "available when coinstatsindex is used)"}, | ||||
{RPCResult::Type::STR_AMOUNT, "total_amount", | {RPCResult::Type::STR_AMOUNT, "total_amount", | ||||
"The total amount"}, | "The total amount"}, | ||||
{RPCResult::Type::STR_AMOUNT, "total_unspendable_amount", | |||||
"The total amount of coins permanently excluded from the UTXO " | |||||
"set (only available if coinstatsindex is used)"}, | |||||
{RPCResult::Type::OBJ, | |||||
"block_info", | |||||
"Info on amounts in the block at this block height (only " | |||||
"available if coinstatsindex is used)", | |||||
{{RPCResult::Type::STR_AMOUNT, "prevout_spent", ""}, | |||||
{RPCResult::Type::STR_AMOUNT, "coinbase", ""}, | |||||
{RPCResult::Type::STR_AMOUNT, "new_outputs_ex_coinbase", ""}, | |||||
{RPCResult::Type::STR_AMOUNT, "unspendable", ""}, | |||||
{RPCResult::Type::OBJ, | |||||
"unspendables", | |||||
"Detailed view of the unspendable categories", | |||||
{ | |||||
{RPCResult::Type::STR_AMOUNT, "genesis_block", ""}, | |||||
{RPCResult::Type::STR_AMOUNT, "bip30", | |||||
"Transactions overridden by duplicates (no longer " | |||||
"possible with BIP30)"}, | |||||
{RPCResult::Type::STR_AMOUNT, "scripts", | |||||
"Amounts sent to scripts that are unspendable (for " | |||||
"example OP_RETURN outputs)"}, | |||||
{RPCResult::Type::STR_AMOUNT, "unclaimed_rewards", | |||||
"Fee rewards that miners did not claim in their " | |||||
"coinbase transaction"}, | |||||
}}}}, | |||||
}}, | }}, | ||||
RPCExamples{ | RPCExamples{ | ||||
HelpExampleCli("gettxoutsetinfo", "") + | HelpExampleCli("gettxoutsetinfo", "") + | ||||
HelpExampleCli("gettxoutsetinfo", R"("none")") + | HelpExampleCli("gettxoutsetinfo", R"("none")") + | ||||
HelpExampleCli("gettxoutsetinfo", R"("none" 1000)") + | HelpExampleCli("gettxoutsetinfo", R"("none" 1000)") + | ||||
HelpExampleCli( | HelpExampleCli( | ||||
"gettxoutsetinfo", | "gettxoutsetinfo", | ||||
R"("none" '"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"')") + | R"("none" '"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"')") + | ||||
HelpExampleRpc("gettxoutsetinfo", "") + | HelpExampleRpc("gettxoutsetinfo", "") + | ||||
HelpExampleRpc("gettxoutsetinfo", R"("none")") + | HelpExampleRpc("gettxoutsetinfo", R"("none")") + | ||||
HelpExampleRpc("gettxoutsetinfo", R"("none", 1000)") + | HelpExampleRpc("gettxoutsetinfo", R"("none", 1000)") + | ||||
HelpExampleRpc( | HelpExampleRpc( | ||||
"gettxoutsetinfo", | "gettxoutsetinfo", | ||||
R"("none", "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09")")}, | R"("none", "00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09")")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
UniValue ret(UniValue::VOBJ); | UniValue ret(UniValue::VOBJ); | ||||
CBlockIndex *pindex{nullptr}; | CBlockIndex *pindex{nullptr}; | ||||
const CoinStatsHashType hash_type{ | const CoinStatsHashType hash_type{ | ||||
request.params[0].isNull() | request.params[0].isNull() | ||||
? CoinStatsHashType::HASH_SERIALIZED | ? CoinStatsHashType::HASH_SERIALIZED | ||||
: ParseHashType(request.params[0].get_str())}; | : ParseHashType(request.params[0].get_str())}; | ||||
CCoinsStats stats{hash_type}; | CCoinsStats stats{hash_type}; | ||||
NodeContext &node = EnsureAnyNodeContext(request.context); | NodeContext &node = EnsureAnyNodeContext(request.context); | ||||
ChainstateManager &chainman = EnsureChainman(node); | ChainstateManager &chainman = EnsureChainman(node); | ||||
CChainState &active_chainstate = chainman.ActiveChainstate(); | CChainState &active_chainstate = chainman.ActiveChainstate(); | ||||
active_chainstate.ForceFlushStateToDisk(); | active_chainstate.ForceFlushStateToDisk(); | ||||
CCoinsView *coins_view; | CCoinsView *coins_view; | ||||
BlockManager *blockman; | BlockManager *blockman; | ||||
{ | { | ||||
LOCK(::cs_main); | LOCK(::cs_main); | ||||
coins_view = &active_chainstate.CoinsDB(); | coins_view = &active_chainstate.CoinsDB(); | ||||
blockman = &active_chainstate.m_blockman; | blockman = &active_chainstate.m_blockman; | ||||
pindex = blockman->LookupBlockIndex(coins_view->GetBestBlock()); | |||||
} | } | ||||
if (!request.params[1].isNull()) { | if (!request.params[1].isNull()) { | ||||
if (!g_coin_stats_index) { | if (!g_coin_stats_index) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Querying specific block heights " | "Querying specific block heights " | ||||
"requires coinstatsindex"); | "requires coinstatsindex"); | ||||
} | } | ||||
Show All 9 Lines | return RPCHelpMan{ | ||||
ret.pushKV("bogosize", int64_t(stats.nBogoSize)); | ret.pushKV("bogosize", int64_t(stats.nBogoSize)); | ||||
if (hash_type == CoinStatsHashType::HASH_SERIALIZED) { | if (hash_type == CoinStatsHashType::HASH_SERIALIZED) { | ||||
ret.pushKV("hash_serialized", | ret.pushKV("hash_serialized", | ||||
stats.hashSerialized.GetHex()); | stats.hashSerialized.GetHex()); | ||||
} | } | ||||
if (hash_type == CoinStatsHashType::MUHASH) { | if (hash_type == CoinStatsHashType::MUHASH) { | ||||
ret.pushKV("muhash", stats.hashSerialized.GetHex()); | ret.pushKV("muhash", stats.hashSerialized.GetHex()); | ||||
} | } | ||||
ret.pushKV("total_amount", stats.nTotalAmount); | |||||
if (!stats.from_index) { | if (!stats.from_index) { | ||||
ret.pushKV("transactions", | ret.pushKV("transactions", | ||||
static_cast<int64_t>(stats.nTransactions)); | static_cast<int64_t>(stats.nTransactions)); | ||||
ret.pushKV("disk_size", stats.nDiskSize); | ret.pushKV("disk_size", stats.nDiskSize); | ||||
} else { | |||||
ret.pushKV("total_unspendable_amount", | |||||
stats.total_unspendable_amount); | |||||
CCoinsStats prev_stats{hash_type}; | |||||
if (pindex->nHeight > 0) { | |||||
GetUTXOStats( | |||||
coins_view, | |||||
WITH_LOCK(::cs_main, | |||||
return std::ref(g_chainman.m_blockman)), | |||||
prev_stats, node.rpc_interruption_point, | |||||
pindex->pprev); | |||||
} | |||||
UniValue block_info(UniValue::VOBJ); | |||||
block_info.pushKV( | |||||
"prevout_spent", | |||||
stats.total_prevout_spent_amount - | |||||
prev_stats.total_prevout_spent_amount); | |||||
block_info.pushKV("coinbase", | |||||
stats.total_coinbase_amount - | |||||
prev_stats.total_coinbase_amount); | |||||
block_info.pushKV( | |||||
"new_outputs_ex_coinbase", | |||||
stats.total_new_outputs_ex_coinbase_amount - | |||||
prev_stats.total_new_outputs_ex_coinbase_amount); | |||||
block_info.pushKV("unspendable", | |||||
stats.total_unspendable_amount - | |||||
prev_stats.total_unspendable_amount); | |||||
UniValue unspendables(UniValue::VOBJ); | |||||
unspendables.pushKV( | |||||
"genesis_block", | |||||
stats.total_unspendables_genesis_block - | |||||
prev_stats.total_unspendables_genesis_block); | |||||
unspendables.pushKV( | |||||
"bip30", stats.total_unspendables_bip30 - | |||||
prev_stats.total_unspendables_bip30); | |||||
unspendables.pushKV( | |||||
"scripts", stats.total_unspendables_scripts - | |||||
prev_stats.total_unspendables_scripts); | |||||
unspendables.pushKV( | |||||
"unclaimed_rewards", | |||||
stats.total_unspendables_unclaimed_rewards - | |||||
prev_stats.total_unspendables_unclaimed_rewards); | |||||
block_info.pushKV("unspendables", unspendables); | |||||
ret.pushKV("block_info", block_info); | |||||
} | } | ||||
ret.pushKV("total_amount", stats.nTotalAmount); | |||||
} else { | } else { | ||||
if (g_coin_stats_index) { | if (g_coin_stats_index) { | ||||
const IndexSummary summary{ | const IndexSummary summary{ | ||||
g_coin_stats_index->GetSummary()}; | g_coin_stats_index->GetSummary()}; | ||||
if (!summary.synced) { | if (!summary.synced) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INTERNAL_ERROR, | RPC_INTERNAL_ERROR, | ||||
▲ Show 20 Lines • Show All 1,840 Lines • Show Last 20 Lines |