Skip to content

Commit 90926db

Browse files
committed
Merge #11021: [rpc] fix getchaintxstats()
07704c1 Add some tests for getchaintxstats (Akio Nakamura) 3336676 Fix getchaintxstats() (Akio Nakamura) Pull request description: 1. calculate nblocks more adaptive. -> set default nblocks to min (blocks for 1 month, target block's height - 1) -> before PR: if not specify nblocks-parameter, illegal parameter error will happen when target block height is below nblocks. 2. correct error message. -> nblocks accepts [1 .. block's height -1] . so add a word "-1". 3. add check 0-divide. -> if nTimeDiff = 0 then use UniValue(UniValue::VNULL) and returns {... "txrate": null} . -> before PR: if nTimeDiff = 0 then returns {... "txrate":} and bitcoin-cli cannot handle the response. Tree-SHA512: e1962ce7bb05a5bc7dec03eb04a8e7578f50fdb68927fcfc0a2232905ef4d679293eee148ebe0866682d209a8c458d21fbe71715e7311adb81f37089aae1ed93
2 parents 339da9c + 07704c1 commit 90926db

File tree

2 files changed

+44
-10
lines changed

2 files changed

+44
-10
lines changed

src/rpc/blockchain.cpp

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1484,9 +1484,12 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
14841484
"2. \"blockhash\" (string, optional) The hash of the block that ends the window.\n"
14851485
"\nResult:\n"
14861486
"{\n"
1487-
" \"time\": xxxxx, (numeric) The timestamp for the statistics in UNIX format.\n"
1488-
" \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
1489-
" \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window.\n"
1487+
" \"time\": xxxxx, (numeric) The timestamp for the final block in the window in UNIX format.\n"
1488+
" \"txcount\": xxxxx, (numeric) The total number of transactions in the chain up to that point.\n"
1489+
" \"window_block_count\": xxxxx, (numeric) Size of the window in number of blocks.\n"
1490+
" \"window_tx_count\": xxxxx, (numeric) The number of transactions in the window. Only returned if \"window_block_count\" is > 0.\n"
1491+
" \"window_interval\": xxxxx, (numeric) The elapsed time in the window in seconds. Only returned if \"window_block_count\" is > 0.\n"
1492+
" \"txrate\": x.xx, (numeric) The average rate of transactions per second in the window. Only returned if \"window_interval\" is > 0.\n"
14901493
"}\n"
14911494
"\nExamples:\n"
14921495
+ HelpExampleCli("getchaintxstats", "")
@@ -1496,10 +1499,6 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
14961499
const CBlockIndex* pindex;
14971500
int blockcount = 30 * 24 * 60 * 60 / Params().GetConsensus().nPowTargetSpacing; // By default: 1 month
14981501

1499-
if (!request.params[0].isNull()) {
1500-
blockcount = request.params[0].get_int();
1501-
}
1502-
15031502
bool havehash = !request.params[1].isNull();
15041503
uint256 hash;
15051504
if (havehash) {
@@ -1524,8 +1523,14 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
15241523

15251524
assert(pindex != nullptr);
15261525

1527-
if (blockcount < 1 || blockcount >= pindex->nHeight) {
1528-
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 1 and the block's height");
1526+
if (request.params[0].isNull()) {
1527+
blockcount = std::max(0, std::min(blockcount, pindex->nHeight - 1));
1528+
} else {
1529+
blockcount = request.params[0].get_int();
1530+
1531+
if (blockcount < 0 || (blockcount > 0 && blockcount >= pindex->nHeight)) {
1532+
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid block count: should be between 0 and the block's height - 1");
1533+
}
15291534
}
15301535

15311536
const CBlockIndex* pindexPast = pindex->GetAncestor(pindex->nHeight - blockcount);
@@ -1535,7 +1540,14 @@ UniValue getchaintxstats(const JSONRPCRequest& request)
15351540
UniValue ret(UniValue::VOBJ);
15361541
ret.push_back(Pair("time", (int64_t)pindex->nTime));
15371542
ret.push_back(Pair("txcount", (int64_t)pindex->nChainTx));
1538-
ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff));
1543+
ret.push_back(Pair("window_block_count", blockcount));
1544+
if (blockcount > 0) {
1545+
ret.push_back(Pair("window_tx_count", nTxDiff));
1546+
ret.push_back(Pair("window_interval", nTimeDiff));
1547+
if (nTimeDiff > 0) {
1548+
ret.push_back(Pair("txrate", ((double)nTxDiff) / nTimeDiff));
1549+
}
1550+
}
15391551

15401552
return ret;
15411553
}

test/functional/blockchain.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,28 @@ def _test_getchaintxstats(self):
8181
# we have to round because of binary math
8282
assert_equal(round(chaintxstats['txrate'] * 600, 10), Decimal(1))
8383

84+
b1 = self.nodes[0].getblock(self.nodes[0].getblockhash(1))
85+
b200 = self.nodes[0].getblock(self.nodes[0].getblockhash(200))
86+
time_diff = b200['mediantime'] - b1['mediantime']
87+
88+
chaintxstats = self.nodes[0].getchaintxstats()
89+
assert_equal(chaintxstats['time'], b200['time'])
90+
assert_equal(chaintxstats['txcount'], 201)
91+
assert_equal(chaintxstats['window_block_count'], 199)
92+
assert_equal(chaintxstats['window_tx_count'], 199)
93+
assert_equal(chaintxstats['window_interval'], time_diff)
94+
assert_equal(round(chaintxstats['txrate'] * time_diff, 10), Decimal(199))
95+
96+
chaintxstats = self.nodes[0].getchaintxstats(blockhash=b1['hash'])
97+
assert_equal(chaintxstats['time'], b1['time'])
98+
assert_equal(chaintxstats['txcount'], 2)
99+
assert_equal(chaintxstats['window_block_count'], 0)
100+
assert('window_tx_count' not in chaintxstats)
101+
assert('window_interval' not in chaintxstats)
102+
assert('txrate' not in chaintxstats)
103+
104+
assert_raises_jsonrpc(-8, "Invalid block count: should be between 0 and the block's height - 1", self.nodes[0].getchaintxstats, 201)
105+
84106
def _test_gettxoutsetinfo(self):
85107
node = self.nodes[0]
86108
res = node.gettxoutsetinfo()

0 commit comments

Comments
 (0)