|
|
@ -1944,177 +1944,6 @@ inline CBlockIndex* LookupBlockIndex(const uint256& hash) |
|
|
|
|
|
|
|
#define ORG(X) (X - blockcount - nNotarizationsDiff) |
|
|
|
|
|
|
|
UniValue getchaintxstats(const UniValue& params, bool fHelp) |
|
|
|
{ |
|
|
|
if (fHelp || params.size() > 2) |
|
|
|
throw runtime_error( |
|
|
|
"getchaintxstats\n" |
|
|
|
"\nCompute statistics about the total number and rate of transactions in the chain.\n" |
|
|
|
"\nThis RPC will return extra data about shielded transactions, payments and notarizations if the zindex is enabled .\n" |
|
|
|
"\nArguments:\n" |
|
|
|
"1. nblocks (numeric, optional) Number of blocks in averaging window.\n" |
|
|
|
"2. blockhash (string, optional) The hash of the block which ends the window.\n" |
|
|
|
"\nResult:\n" |
|
|
|
"{\n" |
|
|
|
" \"time\": xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n" |
|
|
|
" \"notarizations\": xxxxx, (optional, numeric) The number of notarizations in the chain.\n" |
|
|
|
" \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n" |
|
|
|
" \"window_final_block_hash\": \"...\", (string) The hash of the final block in the window.\n" |
|
|
|
" \"window_block_count\": xxxxx, (numeric) Size of the window in number of blocks.\n" |
|
|
|
" \"window_notarizations\": xxxxx, (optional, numeric) Number of notarization transactions in window.\n" |
|
|
|
" \"window_tx_count\": xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n" |
|
|
|
" \"window_interval\": xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n" |
|
|
|
" \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\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 (params[1].isNull()) { |
|
|
|
LOCK(cs_main); |
|
|
|
pindex = chainActive.Tip(); |
|
|
|
} else { |
|
|
|
uint256 hash(ParseHashV(params[1], "blockhash")); |
|
|
|
LOCK(cs_main); |
|
|
|
pindex = LookupBlockIndex(hash); |
|
|
|
if (!pindex) { |
|
|
|
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); |
|
|
|
} |
|
|
|
if (!chainActive.Contains(pindex)) { |
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block is not in main chain"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
assert(pindex != nullptr); |
|
|
|
|
|
|
|
if (params[0].isNull()) { |
|
|
|
blockcount = std::max(0, std::min(blockcount, pindex->GetHeight() - 1)); |
|
|
|
} else { |
|
|
|
blockcount = params[0].get_int(); |
|
|
|
|
|
|
|
if (blockcount < 0 || (blockcount > 0 && blockcount >= pindex->GetHeight())) { |
|
|
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 0 and the block's height - 1"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->GetHeight() - blockcount); |
|
|
|
int nTimeDiff = pindex->GetMedianTimePast() - pindexPast->GetMedianTimePast(); |
|
|
|
int nTxDiff = pindex->nChainTx - pindexPast->nChainTx; |
|
|
|
|
|
|
|
UniValue ret(UniValue::VOBJ); |
|
|
|
ret.pushKV("time", (int64_t)pindex->nTime); |
|
|
|
ret.pushKV("txcount", (int64_t)pindex->nChainTx); |
|
|
|
|
|
|
|
if (fZindex) { |
|
|
|
ret.pushKV("notarizations", (int64_t)pindex->nChainNotarizations); |
|
|
|
ret.pushKV("shielded_txcount", (int64_t)pindex->nChainShieldedTx); |
|
|
|
ret.pushKV("fully_shielded_txcount", (int64_t)pindex->nChainFullyShieldedTx); |
|
|
|
ret.pushKV("deshielding_txcount", (int64_t)pindex->nChainDeshieldingTx); |
|
|
|
ret.pushKV("shielding_txcount", (int64_t)pindex->nChainShieldingTx); |
|
|
|
ret.pushKV("shielded_payments", (int64_t)pindex->nChainShieldedPayments); |
|
|
|
ret.pushKV("fully_shielded_payments",(int64_t)pindex->nChainFullyShieldedPayments); |
|
|
|
ret.pushKV("deshielding_payments", (int64_t)pindex->nChainDeshieldingPayments); |
|
|
|
ret.pushKV("shielding_payments", (int64_t)pindex->nChainShieldingPayments); |
|
|
|
} |
|
|
|
|
|
|
|
ret.pushKV("window_final_block_hash", pindex->GetBlockHash().GetHex()); |
|
|
|
ret.pushKV("window_final_block_height", pindex->GetHeight()); |
|
|
|
ret.pushKV("window_block_count", blockcount); |
|
|
|
|
|
|
|
if (blockcount > 0) { |
|
|
|
int64_t nPaymentsDiff = pindex->nChainPayments - pindexPast->nChainPayments; |
|
|
|
int64_t nShieldedTxDiff = pindex->nChainShieldedTx - pindexPast->nChainShieldedTx; |
|
|
|
int64_t nShieldingTxDiff = pindex->nChainShieldingTx - pindexPast->nChainShieldingTx; |
|
|
|
int64_t nDeshieldingTxDiff = pindex->nChainDeshieldingTx - pindexPast->nChainDeshieldingTx; |
|
|
|
int64_t nFullyShieldedTxDiff = pindex->nChainFullyShieldedTx - pindexPast->nChainFullyShieldedTx; |
|
|
|
int64_t nShieldedPaymentsDiff = pindex->nChainShieldedPayments - pindexPast->nChainShieldedPayments; |
|
|
|
int64_t nShieldingPaymentsDiff = pindex->nChainShieldingPayments - pindexPast->nChainShieldingPayments; |
|
|
|
int64_t nDeshieldingPaymentsDiff = pindex->nChainDeshieldingPayments - pindexPast->nChainDeshieldingPayments; |
|
|
|
int64_t nFullyShieldedPaymentsDiff = pindex->nChainFullyShieldedPayments - pindexPast->nChainFullyShieldedPayments; |
|
|
|
unsigned int nNotarizationsDiff = pindex->nChainNotarizations - pindexPast->nChainNotarizations; |
|
|
|
|
|
|
|
ret.pushKV("window_interval", nTimeDiff); |
|
|
|
ret.pushKV("window_txcount", nTxDiff); |
|
|
|
ret.pushKV("window_payments", nPaymentsDiff); |
|
|
|
ret.pushKV("window_notarizations", (int) nNotarizationsDiff); |
|
|
|
|
|
|
|
if (nTimeDiff > 0) { |
|
|
|
ret.pushKV("txrate", ((double)nTxDiff) / nTimeDiff); |
|
|
|
if (fZindex) { |
|
|
|
ret.pushKV("notarization_txrate", ((double)nNotarizationsDiff) / nTimeDiff); |
|
|
|
ret.pushKV("shielded_txrate", ((double)nShieldedTxDiff) / nTimeDiff); |
|
|
|
ret.pushKV("shielding_txrate", ((double)nShieldingTxDiff) / nTimeDiff); |
|
|
|
ret.pushKV("deshielding_txrate", ((double)nDeshieldingTxDiff) / nTimeDiff); |
|
|
|
ret.pushKV("fully_shielded_txrate", ((double)nFullyShieldedTxDiff) / nTimeDiff); |
|
|
|
ret.pushKV("paymentrate", ((double)nPaymentsDiff) / nTimeDiff); |
|
|
|
ret.pushKV("shielded_paymentrate", ((double)nShieldedPaymentsDiff) / nTimeDiff); |
|
|
|
ret.pushKV("fully_shielded_paymentrate", ((double)nFullyShieldedPaymentsDiff) / nTimeDiff); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (fZindex) { |
|
|
|
ret.pushKV("window_fully_shielded_payments", nFullyShieldedPaymentsDiff); |
|
|
|
ret.pushKV("window_shielded_payments", nShieldedPaymentsDiff); |
|
|
|
ret.pushKV("window_shielding_payments", nShieldingPaymentsDiff); |
|
|
|
ret.pushKV("window_deshielding_payments", nDeshieldingPaymentsDiff); |
|
|
|
ret.pushKV("window_shielded_txcount", nShieldedTxDiff); |
|
|
|
|
|
|
|
if (nTxDiff > 0) { |
|
|
|
ret.pushKV("shielded_tx_percent", ((double)nShieldedTxDiff) / nTxDiff); |
|
|
|
ret.pushKV("fully_shielded_tx_percent", ((double)nFullyShieldedTxDiff) / nTxDiff); |
|
|
|
ret.pushKV("shielding_tx_percent", ((double)nShieldingTxDiff) / nTxDiff); |
|
|
|
ret.pushKV("deshielding_tx_percent", ((double)nDeshieldingTxDiff) / nTxDiff); |
|
|
|
} |
|
|
|
if (nPaymentsDiff > 0) { |
|
|
|
ret.pushKV("shielded_payments_percent", ((double)nShieldedPaymentsDiff) / nPaymentsDiff); |
|
|
|
ret.pushKV("fully_shielded_payments_percent", ((double)nFullyShieldedPaymentsDiff) / nPaymentsDiff); |
|
|
|
ret.pushKV("shielding_payments_percent", ((double)nShieldingPaymentsDiff) / nPaymentsDiff); |
|
|
|
ret.pushKV("deshielding_payments_percent", ((double)nDeshieldingPaymentsDiff) / nPaymentsDiff); |
|
|
|
} |
|
|
|
|
|
|
|
// Shielded-only statistics
|
|
|
|
UniValue shielded(UniValue::VOBJ); |
|
|
|
if (nShieldedTxDiff > 0) { |
|
|
|
shielded.pushKV("fully_shielded_tx_percent", ((double)nFullyShieldedTxDiff) / nShieldedTxDiff ); |
|
|
|
shielded.pushKV("shielding_tx_percent", ((double)nShieldingTxDiff) / nShieldedTxDiff ); |
|
|
|
shielded.pushKV("deshielding_tx_percent", ((double)nDeshieldingTxDiff) / nShieldedTxDiff ); |
|
|
|
} |
|
|
|
if (nShieldedPaymentsDiff > 0) { |
|
|
|
shielded.pushKV("fully_shielded_payments_percent", ((double)nFullyShieldedPaymentsDiff) / nShieldedPaymentsDiff ); |
|
|
|
shielded.pushKV("shielding_payments_percent", ((double)nShieldingPaymentsDiff) / nShieldedPaymentsDiff ); |
|
|
|
shielded.pushKV("deshielding_payments_percent", ((double)nDeshieldingPaymentsDiff) / nShieldedPaymentsDiff ); |
|
|
|
} |
|
|
|
if(nShieldedTxDiff+nShieldedPaymentsDiff > 0) |
|
|
|
ret.pushKV("shielded", shielded); |
|
|
|
|
|
|
|
// Organic tx stats = Raw - Coinbase - DPoW
|
|
|
|
if (nTxDiff > 0) { |
|
|
|
UniValue organic(UniValue::VOBJ); |
|
|
|
|
|
|
|
organic.pushKV("shielded_tx_percent", ((double)nShieldedTxDiff) / ORG(nTxDiff)); |
|
|
|
organic.pushKV("fully_shielded_tx_percent", ((double)nFullyShieldedTxDiff) / ORG(nTxDiff)); |
|
|
|
organic.pushKV("shielding_tx_percent", ((double)nShieldingTxDiff) / ORG(nTxDiff)); |
|
|
|
organic.pushKV("deshielding_tx_percent", ((double)nDeshieldingTxDiff) / ORG(nTxDiff)); |
|
|
|
organic.pushKV("shielded_payments_percent", ((double)nShieldedPaymentsDiff) / ORG(nPaymentsDiff)); |
|
|
|
organic.pushKV("fully_shielded_payments_percent", ((double)nFullyShieldedPaymentsDiff) / ORG(nPaymentsDiff)); |
|
|
|
organic.pushKV("shielding_payments_percent", ((double)nShieldingPaymentsDiff) / ORG(nPaymentsDiff)); |
|
|
|
organic.pushKV("deshielding_payments_percent", ((double)nDeshieldingPaymentsDiff) / ORG(nPaymentsDiff)); |
|
|
|
organic.pushKV("paymentrate", ((double)ORG(nPaymentsDiff)) / nTimeDiff); |
|
|
|
organic.pushKV("txrate", ((double)ORG(nTxDiff)) / nTimeDiff); |
|
|
|
organic.pushKV("txcount", (int) ORG(nTxDiff)); |
|
|
|
organic.pushKV("payments", (int) ORG(nPaymentsDiff)); |
|
|
|
ret.pushKV("organic", organic); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
UniValue invalidateblock(const UniValue& params, bool fHelp) |
|
|
|
{ |
|
|
|
if (fHelp || params.size() != 1) |
|
|
@ -2202,7 +2031,6 @@ static const CRPCCommand commands[] = |
|
|
|
{ "blockchain", "getblockhash", &getblockhash, true }, |
|
|
|
{ "blockchain", "getblockheader", &getblockheader, true }, |
|
|
|
{ "blockchain", "getchaintips", &getchaintips, true }, |
|
|
|
{ "blockchain", "getchaintxstats", &getchaintxstats, true }, |
|
|
|
{ "blockchain", "getdifficulty", &getdifficulty, true }, |
|
|
|
{ "blockchain", "getmempoolinfo", &getmempoolinfo, true }, |
|
|
|
{ "blockchain", "getrawmempool", &getrawmempool, true }, |
|
|
|