Skip to content

Commit 21c42c2

Browse files
committed
rpc: Add dumpcoinstats
This RPC dumps the full content of the coinstats index to a CSV file.
1 parent d0609b1 commit 21c42c2

File tree

1 file changed

+71
-0
lines changed

1 file changed

+71
-0
lines changed

src/rpc/blockchain.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <txdb.h>
3131
#include <txmempool.h>
3232
#include <undo.h>
33+
#include <util/moneystr.h>
3334
#include <util/ref.h>
3435
#include <util/strencodings.h>
3536
#include <util/system.h>
@@ -1000,6 +1001,75 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
10001001
return uint64_t(block->nHeight);
10011002
}
10021003

1004+
static UniValue dumpcoinstats(const JSONRPCRequest& request)
1005+
{
1006+
RPCHelpMan{"dumpcoinstats",
1007+
"\nDumps content of coinstats index to a CSV file.\n",
1008+
{
1009+
{"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The filename with path (absolute path recommended)"},
1010+
},
1011+
RPCResult{
1012+
RPCResult::Type::OBJ, "", "",
1013+
{
1014+
{RPCResult::Type::STR, "filename", "The filename with full absolute path"},
1015+
}
1016+
},
1017+
RPCExamples{
1018+
HelpExampleCli("dumpcoinstats", "\"test\"") +
1019+
HelpExampleRpc("dumpcoinstats", "\"test\"")
1020+
},
1021+
}.Check(request);
1022+
1023+
fs::path filepath = request.params[0].get_str();
1024+
filepath = fs::absolute(filepath);
1025+
1026+
if (fs::exists(filepath)) {
1027+
throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.string() + " already exists. If you are sure this is what you want, move it out of the way first");
1028+
}
1029+
1030+
fsbridge::ofstream file;
1031+
file.open(filepath);
1032+
if (!file.is_open())
1033+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open dump file");
1034+
1035+
if (!g_coin_stats_index) {
1036+
throw JSONRPCError(RPC_MISC_ERROR, "Coinstats index is not enabled");
1037+
}
1038+
1039+
file << strprintf("height,bestblock,txouts,bogosize,disk_size,total_amount,total_unspendable_amount,unspendable_amount,total_prevout_spent_amount,total_new_outputs_ex_coinbase_amount,coinbase_amount\n");
1040+
1041+
CCoinsStats stats;
1042+
CCoinsView* coins_view = WITH_LOCK(cs_main, return &ChainstateActive().CoinsDB());
1043+
CBlockIndex *pindex = ::ChainActive().Genesis();
1044+
NodeContext& node = EnsureNodeContext(request.context);
1045+
1046+
for (; pindex; pindex = ::ChainActive().Next(pindex)) {
1047+
if (!GetUTXOStats(coins_view, stats, CoinStatsHashType::NONE, node.rpc_interruption_point, pindex))
1048+
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set");
1049+
1050+
file << strprintf("%d,", (int64_t)stats.nHeight);
1051+
file << strprintf("%s,", stats.hashBlock.GetHex());
1052+
file << strprintf("%d,", (int64_t)stats.nTransactionOutputs);
1053+
file << strprintf("%d,", (int64_t)stats.nBogoSize);
1054+
file << strprintf("%d,", stats.nDiskSize);
1055+
file << strprintf("%s,", FormatMoney(stats.nTotalAmount));
1056+
file << strprintf("%s,", FormatMoney(stats.total_unspendable_amount));
1057+
file << strprintf("%s,", FormatMoney(stats.block_unspendable_amount));
1058+
file << strprintf("%s,", FormatMoney(stats.block_prevout_spent_amount));
1059+
file << strprintf("%s,", FormatMoney(stats.block_new_outputs_ex_coinbase_amount));
1060+
file << strprintf("%s\n", FormatMoney(stats.block_coinbase_amount));
1061+
1062+
if (pindex->nHeight >= ::ChainActive().Tip()->nHeight) break;
1063+
}
1064+
1065+
file.close();
1066+
1067+
UniValue response(UniValue::VOBJ);
1068+
response.pushKV("filename", filepath.string());
1069+
1070+
return response;
1071+
}
1072+
10031073
static UniValue gettxoutsetinfo(const JSONRPCRequest& request)
10041074
{
10051075
RPCHelpMan{"gettxoutsetinfo",
@@ -2436,6 +2506,7 @@ static const CRPCCommand commands[] =
24362506
{ "blockchain", "getrawmempool", &getrawmempool, {"verbose"} },
24372507
{ "blockchain", "gettxout", &gettxout, {"txid","n","include_mempool"} },
24382508
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, {"hash_type", "hash_or_height", "verbose"} },
2509+
{ "blockchain", "dumpcoinstats", &dumpcoinstats, {"filename"} },
24392510
{ "blockchain", "pruneblockchain", &pruneblockchain, {"height"} },
24402511
{ "blockchain", "savemempool", &savemempool, {} },
24412512
{ "blockchain", "verifychain", &verifychain, {"checklevel","nblocks"} },

0 commit comments

Comments
 (0)