-
Notifications
You must be signed in to change notification settings - Fork 37.7k
rpc, test: Improve getblockstats for unspendables #19888
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
3b40c6f
to
bb608b7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bb608b7
to
defaac4
Compare
The genesis block has no effect on the utxo set, so the returned result is wrong |
defaac4
to
c266571
Compare
Heh, yeah, the whole RPC actually didn't deal with unspendables at all so far. I am fixing this with my latest changes, fixing the Genesis block but also BIP30 and unspendable outputs. I think the numbers make much more sense this way. I also needed to regenerate the test data because the witness commitment is now excluded from the stats. |
Concept ACK |
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ConflictsReviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first. |
src/rpc/blockchain.cpp
Outdated
@@ -1743,7 +1747,7 @@ static UniValue getblockstats(const JSONRPCRequest& request) | |||
{RPCResult::Type::NUM, "totalfee", "The fee total"}, | |||
{RPCResult::Type::NUM, "txs", "The number of transactions (including coinbase)"}, | |||
{RPCResult::Type::NUM, "utxo_increase", "The increase/decrease in the number of unspent outputs"}, | |||
{RPCResult::Type::NUM, "utxo_size_inc", "The increase/decrease in size for the utxo index (not discounting op_return and similar)"}, | |||
{RPCResult::Type::NUM, "utxo_size_inc", "The increase/decrease in size for the utxo index"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With this change to the documented API, I think you'd better add a new field instead...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Slightly would have preferred to just fix the existing values but I have now introduced new values with a *_actual naming scheme.
src/rpc/blockchain.cpp
Outdated
// set, so they can be excluded from the statistics | ||
const bool is_genesis = pindex->nHeight == 0; | ||
const bool is_bip30_repeat = (pindex->nHeight == 91880 && pindex->GetBlockHash() == uint256S("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")) || | ||
(pindex->nHeight == 91842 && pindex->GetBlockHash() == uint256S("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be nice to abstract this to a block-aware IsUnspendable
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+1, it would be better not to repeat this in multiple places
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but it's a bit more complicated because these blocks' coinbases are not actually unspendable, they are the ones that overwrote the other previous coinbases aifaik. But I have refactored both of these out into helper functions that would also be helpful to me for Coinstatsindex. Let me know what you think about the naming, 'repeat' was the best I came up with.
@@ -160,6 +160,9 @@ def run_test(self): | |||
assert_raises_rpc_error(-1, 'getblockstats hash_or_height ( stats )', self.nodes[0].getblockstats, '00', 1, 2) | |||
assert_raises_rpc_error(-1, 'getblockstats hash_or_height ( stats )', self.nodes[0].getblockstats) | |||
|
|||
self.log.info('Test block height 0') | |||
genesis_stats = self.nodes[0].getblockstats(0) | |||
assert_equal(genesis_stats["blockhash"], "0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be nice to test the other corner-case result values
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure if you had more values in mind (let me know) but I have added the old and new values that this PR touches.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a test with an OP_RETURN
output.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re: #19888 (comment)
Added a test with an
OP_RETURN
output.
Note: This is referring to commit f87d4b9 "Added a test with an OP_RETURN output" I think
c266571
to
37bbfe9
Compare
Addressed feedback comments. Thanks for reviewing and sorry for the long wait! |
@@ -102,8 +102,8 @@ | |||
"00000020f44e7a48b9f221af95f3295c8dcefc5358934a68dc79e2933dc0794b350cad0a90fad2cd50b41d4ef45e76c2a456b98c180632bb4b44e0cd18ce90679fe54e552b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401630101ffffffff0200f2052a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000", | |||
"0000002087454276cce83f4d19e0120f6e9728ac5905f7adaf6b27e3f5bbe43ab823f85db7d1f44666531483df3d67c15f2c231718ad93b63b851dce5ff4c4a67f524ffa2b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401640101ffffffff0200f2052a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000", | |||
"000000202cdc3e99f07a80252dd6097faa0eddf3f2dde5ae390610e0bca94ecc25931551d31fceb8fe0a682f6017ca3dbb582f3a2f06e5d99ec99c42c8a744dd4c9216b82b4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401650101ffffffff0200f2052a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000", | |||
"000000209b3ace9bd510918d20e87518c0cf5976cab3e28cc7af41259a89c6dd7668a32922808b8a082be71bcd6152cb8fd223650b5579a41344ba749e4d17b9bf211a9e2b4ae75affff7f200000000002020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401660101ffffffff026c03062a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9edb85d8f3c122c43a72f1e0dd122c8f7af040aa0b0a46001621110fb37818021510120000000000000000000000000000000000000000000000000000000000000000000000000020000000128394022bf44bff30d7399cb5a16e3b94fed67dc174c2e1d77df91bad5a51cb3000000006a47304402201c16d06a5c4353168b3881071aea7d1eb4d88eedfea53a9d6af9abb56da9060002205abf3ae535f1f1b5cfe8ba955535c2b20ac003e7d7720c5b7d2640ac2a04d19001210227d85ba011276cf25b51df6a188b75e604b38770a462b2d0e9fb2fc839ef5d3ffeffffff0294b89a3b000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac00286bee0000000017a91452bab4f229415d0dc5c6d30b162f93a1a0cac5958765000000", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you retain the old test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done now in this particular commit but now need to regenerate it in another commit :-/
37bbfe9
to
1c18449
Compare
Finally got back to give this the attention it deserves. First of all, it is rebased. Then I followed some recommendation from @luke-jr which also let me to find some other issue. Here is a recap per commit to make it easier to understand what changed: c7ccc07: (unchanged) Refactors BIP30 logic into helper functions. This will also be helpful for #19521 where the logic is currently duplicated as well. |
Rebased and fixed the silent merge conflict noted by @ryanofsky . Thanks! |
Making the checks to identify BIP30 available outside of validation.cpp is needed for reporting and tracking statistics on specific blocks and the UTXO set correctly. Github-Pull: bitcoin#19888 Rebased-From: 1effbfe
- Fix getblockstats for block height 0 which previously returned an error. - Introduce alternative utxo_*_actual statistics which exclude unspendables: Genesis block, BIP30, unspendable outputs - Update test data - Explicitly test Genesis block results Github-Pull: bitcoin#19888 Rebased-From: 0fec5c2
The getblockstats RPC functional test is using previously generated test data that is part of the repository. That test data can be regenerated by running the test file with `--gen-test-data` which invokes the `generate_test_data()` function. That function still relied on the old wallet behavior of having a default wallet to work. Because of this the function was broken and this change fixes this. The fact that this was broken did was not noticed previously because the function is not used by the automated test suite by default. Github-Pull: bitcoin#19888 Rebased-From: 2d7975c
Github-Pull: bitcoin#19888 Rebased-From: ff16851
rebased |
Making the checks to identify BIP30 available outside of validation.cpp is needed for reporting and tracking statistics on specific blocks and the UTXO set correctly.
- Fix getblockstats for block height 0 which previously returned an error. - Introduce alternative utxo_*_actual statistics which exclude unspendables: Genesis block, BIP30, unspendable outputs - Update test data - Explicitly test Genesis block results
The getblockstats RPC functional test is using previously generated test data that is part of the repository. That test data can be regenerated by running the test file with `--gen-test-data` which invokes the `generate_test_data()` function. That function still relied on the old wallet behavior of having a default wallet to work. Because of this the function was broken and this change fixes this. The fact that this was broken did was not noticed previously because the function is not used by the automated test suite by default.
7232bd2
to
d885bb2
Compare
rebased |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK d885bb2
Some end results I tried:
$ diff ./stats_master ./stats_pr # testnet block 000000007be904ff76a13eb6f0a10d945dbdc7a8ce18d66dd62af0d7e31d69fb
36c36,38
< "utxo_size_inc": 614
---
> "utxo_size_inc": 614,
> "utxo_increase_actual": 6,
> "utxo_size_inc_actual": 393
Master
Details
./src/bitcoin-cli getblockstats '"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"' # genesis
error code: -1
error message:
Can't read undo data from disk
./src/bitcoin-cli getblockstats '"00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec"'
{
"avgfee": 0,
"avgfeerate": 0,
"avgtxsize": 0,
"blockhash": "00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec",
"feerate_percentiles": [
0,
0,
0,
0,
0
],
"height": 91842,
"ins": 0,
"maxfee": 0,
"maxfeerate": 0,
"maxtxsize": 0,
"medianfee": 0,
"mediantime": 1289767893,
"mediantxsize": 0,
"minfee": 0,
"minfeerate": 0,
"mintxsize": 0,
"outs": 1,
"subsidy": 5000000000,
"swtotal_size": 0,
"swtotal_weight": 0,
"swtxs": 0,
"time": 1289768691,
"total_out": 0,
"total_size": 0,
"total_weight": 0,
"totalfee": 0,
"txs": 1,
"utxo_increase": 1,
"utxo_size_inc": 117
}
PR
Details
./src/bitcoin-cli getblockstats '"000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"' # genesis
{
"avgfee": 0,
"avgfeerate": 0,
"avgtxsize": 0,
"blockhash": "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f",
"feerate_percentiles": [
0,
0,
0,
0,
0
],
"height": 0,
"ins": 0,
"maxfee": 0,
"maxfeerate": 0,
"maxtxsize": 0,
"medianfee": 0,
"mediantime": 1231006505,
"mediantxsize": 0,
"minfee": 0,
"minfeerate": 0,
"mintxsize": 0,
"outs": 1,
"subsidy": 5000000000,
"swtotal_size": 0,
"swtotal_weight": 0,
"swtxs": 0,
"time": 1231006505,
"total_out": 0,
"total_size": 0,
"total_weight": 0,
"totalfee": 0,
"txs": 1,
"utxo_increase": 1,
"utxo_size_inc": 117,
"utxo_increase_actual": 0,
"utxo_size_inc_actual": 0
}
./src/bitcoin-cli getblockstats '"00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec"'
{
"avgfee": 0,
"avgfeerate": 0,
"avgtxsize": 0,
"blockhash": "00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec",
"feerate_percentiles": [
0,
0,
0,
0,
0
],
"height": 91842,
"ins": 0,
"maxfee": 0,
"maxfeerate": 0,
"maxtxsize": 0,
"medianfee": 0,
"mediantime": 1289767893,
"mediantxsize": 0,
"minfee": 0,
"minfeerate": 0,
"mintxsize": 0,
"outs": 1,
"subsidy": 5000000000,
"swtotal_size": 0,
"swtotal_weight": 0,
"swtxs": 0,
"time": 1289768691,
"total_out": 0,
"total_size": 0,
"total_weight": 0,
"totalfee": 0,
"txs": 1,
"utxo_increase": 1,
"utxo_size_inc": 117,
"utxo_increase_actual": 0,
"utxo_size_inc_actual": 0
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK d885bb2
No blocking comments/okay in follow-up. However, since it's difficult to change RPC variable names after they're part of the public API, might be best to consider that first.
/** Identifies blocks that overwrote an existing coinbase output in the UTXO set (see BIP30) */ | ||
bool IsBIP30Repeat(const CBlockIndex& block_index); | ||
|
||
/** Identifies blocks which coinbase output was subsequently overwritten in the UTXO set (see BIP30) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit (see e.g. this)
/** Identifies blocks which coinbase output was subsequently overwritten in the UTXO set (see BIP30) */ | |
/** Identifies blocks whose coinbase output was subsequently overwritten in the UTXO set (see BIP30) */ |
@@ -1082,4 +1082,10 @@ bool DeploymentEnabled(const ChainstateManager& chainman, DEP dep) | |||
*/ | |||
const AssumeutxoData* ExpectedAssumeutxo(const int height, const CChainParams& params); | |||
|
|||
/** Identifies blocks that overwrote an existing coinbase output in the UTXO set (see BIP30) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit:
/** Identifies blocks that overwrote an existing coinbase output in the UTXO set (see BIP30) */ | |
/** Did this block overwrite an existing coinbase output in the UTXO set? (see BIP30) */ |
/** Identifies blocks that overwrote an existing coinbase output in the UTXO set (see BIP30) */ | ||
bool IsBIP30Repeat(const CBlockIndex& block_index); | ||
|
||
/** Identifies blocks which coinbase output was subsequently overwritten in the UTXO set (see BIP30) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit
/** Identifies blocks which coinbase output was subsequently overwritten in the UTXO set (see BIP30) */ | |
/** Was this block's coinbase output overwritten in the UTXO set by a later block? (see BIP30) */ |
{RPCResult::Type::NUM, "utxo_increase_actual", /*optional=*/true, "The increase/decrease in the number of unspent outputs, not counting unspendables"}, | ||
{RPCResult::Type::NUM, "utxo_size_inc_actual", /*optional=*/true, "The increase/decrease in size for the utxo index, not counting unspendables"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think "actual" is quite vague, "spendable" would be more immediately obvious imo?
{RPCResult::Type::NUM, "utxo_increase_actual", /*optional=*/true, "The increase/decrease in the number of unspent outputs, not counting unspendables"}, | |
{RPCResult::Type::NUM, "utxo_size_inc_actual", /*optional=*/true, "The increase/decrease in size for the utxo index, not counting unspendables"}, | |
{RPCResult::Type::NUM, "utxo_increase_spendable", /*optional=*/true, "The increase/decrease in the number of unspent outputs, not counting unspendables"}, | |
{RPCResult::Type::NUM, "utxo_size_inc_spendable", /*optional=*/true, "The increase/decrease in size for the utxo index, not counting unspendables"}, |
@@ -1771,8 +1775,10 @@ static RPCHelpMan getblockstats() | |||
{RPCResult::Type::NUM, "total_weight", /*optional=*/true, "Total weight of all non-coinbase transactions"}, | |||
{RPCResult::Type::NUM, "totalfee", /*optional=*/true, "The fee total"}, | |||
{RPCResult::Type::NUM, "txs", /*optional=*/true, "The number of transactions (including coinbase)"}, | |||
{RPCResult::Type::NUM, "utxo_increase", /*optional=*/true, "The increase/decrease in the number of unspent outputs"}, | |||
{RPCResult::Type::NUM, "utxo_increase", /*optional=*/true, "The increase/decrease in the number of unspent outputs (not discounting op_return and similar)"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using different terminology here compared to in the 2 new lines makes it less clear what the difference in functionality is. Realigning the phrasing makes sense for readability imo.
"including unspendables such as op_return" and "excluding unspendables such as op_return" makes the difference more immediately obvious I think.
{RPCResult::Type::NUM, "utxo_size_inc", /*optional=*/true, "The increase/decrease in size for the utxo index (not discounting op_return and similar)"}, | ||
{RPCResult::Type::NUM, "utxo_increase_actual", /*optional=*/true, "The increase/decrease in the number of unspent outputs, not counting unspendables"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: every other line is alphabetically sorted, this one isn't
@@ -1825,7 +1831,9 @@ static RPCHelpMan getblockstats() | |||
int64_t swtxs = 0; | |||
int64_t total_size = 0; | |||
int64_t total_weight = 0; | |||
int64_t utxos = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: spendable_utxo_count
would be my preferred, but that doesn't seem to be in line with naming convention here, so I'm happy with:
int64_t utxos = 0; | |
int64_t utxos_spendable = 0; |
tip_stats = self.nodes[0].getblockstats(tip) | ||
assert_equal(tip_stats["utxo_increase"], 6) | ||
assert_equal(tip_stats["utxo_size_inc"], 441) | ||
assert_equal(tip_stats["utxo_increase_actual"], 4) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you mind adding a docstring that explains why 4 (i.e. 2 unspendable UTXOs)? From generate_test_data
it would seem there is only 1 OP_RETURN, and genesis/bip30 wouldn't apply here either?
assert_equal(tip_stats["utxo_size_inc"], 441) | ||
assert_equal(tip_stats["utxo_increase_actual"], 4) | ||
assert_equal(tip_stats["utxo_size_inc_actual"], 300) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When I run --gen-test-data
, I get slightly different sizes: 441->438 and 300->297. Not sure how local ./configure options would change that, so... wondering if it's just me or leftover from using an older wallet version in earlier versions of the PR?
ACK d885bb2 |
Fixes #19885
The genesis block does not have undo data saved to disk so the RPC errored because of that.