aboutsummaryrefslogtreecommitdiff
path: root/src/rpc
diff options
context:
space:
mode:
authorFabian Jahr <fjahr@protonmail.com>2020-08-22 20:21:20 +0200
committerFabian Jahr <fjahr@protonmail.com>2021-04-19 20:31:02 +0200
commit2501576eccb08af80471c7b7b843b189ad6758c0 (patch)
tree31891e04458f1c36128d3418ebc36e3ac5c9253a /src/rpc
parent655d929836a71af23d2035d2e2e99ad8b8c340c3 (diff)
downloadbitcoin-2501576eccb08af80471c7b7b843b189ad6758c0.tar.xz
rpc, index: Add verbose amounts tracking to Coinstats index
Diffstat (limited to 'src/rpc')
-rw-r--r--src/rpc/blockchain.cpp45
-rw-r--r--src/rpc/client.cpp1
2 files changed, 42 insertions, 4 deletions
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index e6bf7f91b7..1067a7c4bb 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -1113,8 +1113,23 @@ static RPCHelpMan gettxoutsetinfo()
{RPCResult::Type::STR_HEX, "hash_serialized_2", /* optional */ true, "The serialized hash (only present if 'hash_serialized_2' hash_type is chosen)"},
{RPCResult::Type::STR_HEX, "muhash", /* optional */ true, "The serialized hash (only present if 'muhash' hash_type is chosen)"},
{RPCResult::Type::NUM, "transactions", "The number of transactions with unspent outputs (not available when coinstatsindex is used)"},
- {RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk"},
+ {RPCResult::Type::NUM, "disk_size", "The estimated size of the chainstate on disk (not available when coinstatsindex is used)"},
{RPCResult::Type::STR_AMOUNT, "total_amount", "The total amount of coins in the UTXO set"},
+ {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{
HelpExampleCli("gettxoutsetinfo", "") +
@@ -1130,9 +1145,7 @@ static RPCHelpMan gettxoutsetinfo()
{
UniValue ret(UniValue::VOBJ);
- ::ChainstateActive().ForceFlushStateToDisk();
CBlockIndex* pindex{nullptr};
-
const CoinStatsHashType hash_type{request.params[0].isNull() ? CoinStatsHashType::HASH_SERIALIZED : ParseHashType(request.params[0].get_str())};
CCoinsStats stats{hash_type};
@@ -1147,6 +1160,7 @@ static RPCHelpMan gettxoutsetinfo()
LOCK(::cs_main);
coins_view = &active_chainstate.CoinsDB();
blockman = &active_chainstate.m_blockman;
+ pindex = blockman->LookupBlockIndex(coins_view->GetBestBlock());
}
if (!request.params[1].isNull()) {
@@ -1168,11 +1182,34 @@ static RPCHelpMan gettxoutsetinfo()
if (hash_type == CoinStatsHashType::MUHASH) {
ret.pushKV("muhash", stats.hashSerialized.GetHex());
}
+ ret.pushKV("total_amount", ValueFromAmount(stats.nTotalAmount));
if (!stats.from_index) {
ret.pushKV("transactions", static_cast<int64_t>(stats.nTransactions));
ret.pushKV("disk_size", stats.nDiskSize);
+ } else {
+ ret.pushKV("total_unspendable_amount", ValueFromAmount(stats.block_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", ValueFromAmount(stats.block_prevout_spent_amount - prev_stats.block_prevout_spent_amount));
+ block_info.pushKV("coinbase", ValueFromAmount(stats.block_coinbase_amount - prev_stats.block_coinbase_amount));
+ block_info.pushKV("new_outputs_ex_coinbase", ValueFromAmount(stats.block_new_outputs_ex_coinbase_amount - prev_stats.block_new_outputs_ex_coinbase_amount));
+ block_info.pushKV("unspendable", ValueFromAmount(stats.block_unspendable_amount - prev_stats.block_unspendable_amount));
+
+ UniValue unspendables(UniValue::VOBJ);
+ unspendables.pushKV("genesis_block", ValueFromAmount(stats.unspendables_genesis_block - prev_stats.unspendables_genesis_block));
+ unspendables.pushKV("bip30", ValueFromAmount(stats.unspendables_bip30 - prev_stats.unspendables_bip30));
+ unspendables.pushKV("scripts", ValueFromAmount(stats.unspendables_scripts - prev_stats.unspendables_scripts));
+ unspendables.pushKV("unclaimed_rewards", ValueFromAmount(stats.unspendables_unclaimed_rewards - prev_stats.unspendables_unclaimed_rewards));
+ block_info.pushKV("unspendables", unspendables);
+
+ ret.pushKV("block_info", block_info);
}
- ret.pushKV("total_amount", ValueFromAmount(stats.nTotalAmount));
} else {
if (g_coin_stats_index) {
const IndexSummary summary{g_coin_stats_index->GetSummary()};
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 2b593cd10b..9ccfa36450 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -127,6 +127,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "gettxout", 1, "n" },
{ "gettxout", 2, "include_mempool" },
{ "gettxoutproof", 0, "txids" },
+ { "gettxoutsetinfo", 1, "hash_or_height" },
{ "lockunspent", 0, "unlock" },
{ "lockunspent", 1, "transactions" },
{ "send", 0, "outputs" },