|
|
|
@ -1415,10 +1415,76 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
@@ -1415,10 +1415,76 @@ UniValue reconsiderblock(const JSONRPCRequest& request)
|
|
|
|
|
return NullUniValue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
UniValue getchaintxstats(const JSONRPCRequest& request) |
|
|
|
|
{ |
|
|
|
|
if (request.fHelp || request.params.size() > 2) |
|
|
|
|
throw std::runtime_error( |
|
|
|
|
"getchaintxstats ( nblocks blockhash )\n" |
|
|
|
|
"\nCompute statistics about the total number and rate of transactions in the chain.\n" |
|
|
|
|
"\nArguments:\n" |
|
|
|
|
"1. nblocks (numeric, optional) Size of the window in number of blocks (default: one month).\n" |
|
|
|
|
"2. \"blockhash\" (string, optional) The hash of the block that ends the window.\n" |
|
|
|
|
"\nResult:\n" |
|
|
|
|
"{\n" |
|
|
|
|
" \"time\": xxxxx, (numeric) The timestamp for the statistics in UNIX format.\n" |
|
|
|
|
" \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n" |
|
|
|
|
" \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window.\n" |
|
|
|
|
"}\n" |
|
|
|
|
"\nExamples:\n" |
|
|
|
|
+ HelpExampleCli("getchaintxstats", "") |
|
|
|
|
+ HelpExampleRpc("getchaintxstats", "2016") |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const CBlockIndex* pindex; |
|
|
|
|
int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month
|
|
|
|
|
|
|
|
|
|
if (request.params.size() > 0 && !request.params[0].isNull()) { |
|
|
|
|
blockcount = request.params[0].get_int(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool havehash = request.params.size() > 1 && !request.params[1].isNull(); |
|
|
|
|
uint256 hash; |
|
|
|
|
if (havehash) { |
|
|
|
|
hash = uint256S(request.params[1].get_str()); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
LOCK(cs_main); |
|
|
|
|
if (havehash) { |
|
|
|
|
auto it = mapBlockIndex.find(hash); |
|
|
|
|
if (it == mapBlockIndex.end()) { |
|
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); |
|
|
|
|
} |
|
|
|
|
pindex = it->second; |
|
|
|
|
if (!chainActive.Contains(pindex)) { |
|
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain"); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
pindex = chainActive.Tip(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (blockcount < 1 || blockcount >= pindex->nHeight) { |
|
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 1 and the block's height"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->nHeight - blockcount); |
|
|
|
|
int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast(); |
|
|
|
|
int nTxDiff = pindex->nChainTx - pindexPast->nChainTx; |
|
|
|
|
|
|
|
|
|
UniValue ret(UniValue::VOBJ); |
|
|
|
|
ret.push_back(Pair("time", (int64_t)pindex->nTime)); |
|
|
|
|
ret.push_back(Pair("txcount", (int64_t)pindex->nChainTx)); |
|
|
|
|
ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff)); |
|
|
|
|
|
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static const CRPCCommand commands[] = |
|
|
|
|
{ // category name actor (function) okSafe argNames
|
|
|
|
|
// --------------------- ------------------------ ----------------------- ------ ----------
|
|
|
|
|
{ "blockchain", "getblockchaininfo", &getblockchaininfo, true, {} }, |
|
|
|
|
{ "blockchain", "getchaintxstats", &getchaintxstats, true, {"nblocks", "blockhash"} }, |
|
|
|
|
{ "blockchain", "getbestblockhash", &getbestblockhash, true, {} }, |
|
|
|
|
{ "blockchain", "getblockcount", &getblockcount, true, {} }, |
|
|
|
|
{ "blockchain", "getblock", &getblock, true, {"blockhash","verbose"} }, |
|
|
|
|