From cb94db119f4643f49da63520d64efc99fb0c0795 Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Thu, 24 Dec 2020 00:11:40 +0100 Subject: [PATCH 1/4] validation, index: Add unspendable coinbase helper functions 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. --- src/index/coinstatsindex.cpp | 6 +----- src/validation.cpp | 15 +++++++++++++-- src/validation.h | 6 ++++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/index/coinstatsindex.cpp b/src/index/coinstatsindex.cpp index d3559b1b75e..271e5bb1f68 100644 --- a/src/index/coinstatsindex.cpp +++ b/src/index/coinstatsindex.cpp @@ -144,17 +144,13 @@ bool CoinStatsIndex::CustomAppend(const interfaces::BlockInfo& block) } } - // TODO: Deduplicate BIP30 related code - bool is_bip30_block{(block.height == 91722 && block.hash == uint256S("0x00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e")) || - (block.height == 91812 && block.hash == uint256S("0x00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f"))}; - // Add the new utxos created from the block assert(block.data); for (size_t i = 0; i < block.data->vtx.size(); ++i) { const auto& tx{block.data->vtx.at(i)}; // Skip duplicate txid coinbase transactions (BIP30). - if (is_bip30_block && tx->IsCoinBase()) { + if (IsBIP30Unspendable(*pindex) && tx->IsCoinBase()) { m_total_unspendable_amount += block_subsidy; m_total_unspendables_bip30 += block_subsidy; continue; diff --git a/src/validation.cpp b/src/validation.cpp index 37e68cfe4a1..e6fa63b5640 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2083,8 +2083,7 @@ bool Chainstate::ConnectBlock(const CBlock& block, BlockValidationState& state, // Now that the whole chain is irreversibly beyond that time it is applied to all blocks except the // two in the chain that violate it. This prevents exploiting the issue against nodes during their // initial block download. - bool fEnforceBIP30 = !((pindex->nHeight==91842 && pindex->GetBlockHash() == uint256S("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) || - (pindex->nHeight==91880 && pindex->GetBlockHash() == uint256S("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721"))); + bool fEnforceBIP30 = !IsBIP30Repeat(*pindex); // Once BIP34 activated it was not possible to create new duplicate coinbases and thus other than starting // with the 2 existing duplicate coinbase pairs, not possible to create overwriting txs. But by the @@ -5290,3 +5289,15 @@ Chainstate& ChainstateManager::ActivateExistingSnapshot(CTxMemPool* mempool, uin m_active_chainstate = m_snapshot_chainstate.get(); return *m_snapshot_chainstate; } + +bool IsBIP30Repeat(const CBlockIndex& block_index) +{ + return (block_index.nHeight==91842 && block_index.GetBlockHash() == uint256S("0x00000000000a4d0a398161ffc163c503763b1f4360639393e0e4c8e300e0caec")) || + (block_index.nHeight==91880 && block_index.GetBlockHash() == uint256S("0x00000000000743f190a18c5577a3c2d2a1f610ae9601ac046a38084ccb7cd721")); +} + +bool IsBIP30Unspendable(const CBlockIndex& block_index) +{ + return (block_index.nHeight==91722 && block_index.GetBlockHash() == uint256S("0x00000000000271a2dc26e7667f8419f2e15416dc6955e5a6c6cdf3f2574dd08e")) || + (block_index.nHeight==91812 && block_index.GetBlockHash() == uint256S("0x00000000000af0aed4792b1acee3d966af36cf5def14935db8de83d6f9306f2f")); +} diff --git a/src/validation.h b/src/validation.h index fb6d59f92ed..a8ef7a8b3ae 100644 --- a/src/validation.h +++ b/src/validation.h @@ -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) */ +bool IsBIP30Repeat(const CBlockIndex& block_index); + +/** Identifies blocks which coinbase output was subsequently overwritten in the UTXO set (see BIP30) */ +bool IsBIP30Unspendable(const CBlockIndex& block_index); + #endif // BITCOIN_VALIDATION_H From 2ca5a496c2f3cbcc63ea15fa05c1658e7f527bbc Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Sun, 6 Sep 2020 00:22:19 +0200 Subject: [PATCH 2/4] rpc: Improve getblockstats - 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 --- src/rpc/blockchain.cpp | 31 ++++++++++++++++++--- test/functional/data/rpc_getblockstats.json | 14 +++++++--- test/functional/rpc_getblockstats.py | 8 ++++++ 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index f8ba822f54f..3adbadb9b0c 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -593,6 +593,10 @@ static CBlockUndo GetUndoChecked(BlockManager& blockman, const CBlockIndex* pblo { AssertLockHeld(::cs_main); CBlockUndo blockUndo; + + // The Genesis block does not have undo data + if (pblockindex->nHeight == 0) return blockUndo; + if (blockman.IsBlockPruned(pblockindex)) { throw JSONRPCError(RPC_MISC_ERROR, "Undo data not available (pruned data)"); } @@ -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)"}, {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"}, + {RPCResult::Type::NUM, "utxo_size_inc_actual", /*optional=*/true, "The increase/decrease in size for the utxo index, not counting unspendables"}, }}, RPCExamples{ HelpExampleCli("getblockstats", R"('"00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09"' '["minfeerate","avgfeerate"]')") + @@ -1803,7 +1809,7 @@ static RPCHelpMan getblockstats() const bool do_medianfee = do_all || stats.count("medianfee") != 0; const bool do_feerate_percentiles = do_all || stats.count("feerate_percentiles") != 0; const bool loop_inputs = do_all || do_medianfee || do_feerate_percentiles || - SetHasKeys(stats, "utxo_size_inc", "totalfee", "avgfee", "avgfeerate", "minfee", "maxfee", "minfeerate", "maxfeerate"); + SetHasKeys(stats, "utxo_increase", "utxo_increase_actual", "utxo_size_inc", "utxo_size_inc_actual", "totalfee", "avgfee", "avgfeerate", "minfee", "maxfee", "minfeerate", "maxfeerate"); const bool loop_outputs = do_all || loop_inputs || stats.count("total_out"); const bool do_calculate_size = do_mediantxsize || SetHasKeys(stats, "total_size", "avgtxsize", "mintxsize", "maxtxsize", "swtotal_size"); @@ -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; int64_t utxo_size_inc = 0; + int64_t utxo_size_inc_actual = 0; std::vector fee_array; std::vector> feerate_array; std::vector txsize_array; @@ -1838,7 +1846,18 @@ static RPCHelpMan getblockstats() if (loop_outputs) { for (const CTxOut& out : tx->vout) { tx_total_out += out.nValue; - utxo_size_inc += GetSerializeSize(out, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD; + + size_t out_size = GetSerializeSize(out, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD; + utxo_size_inc += out_size; + + // The Genesis block and the repeated BIP30 block coinbases don't change the UTXO + // set counts, so they have to be excluded from the statistics + if (pindex.nHeight == 0 || (IsBIP30Repeat(pindex) && tx->IsCoinBase())) continue; + // Skip unspendable outputs since they are not included in the UTXO set + if (out.scriptPubKey.IsUnspendable()) continue; + + ++utxos; + utxo_size_inc_actual += out_size; } } @@ -1880,7 +1899,9 @@ static RPCHelpMan getblockstats() const CTxOut& prevoutput = coin.out; tx_total_in += prevoutput.nValue; - utxo_size_inc -= GetSerializeSize(prevoutput, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD; + size_t prevout_size = GetSerializeSize(prevoutput, PROTOCOL_VERSION) + PER_UTXO_OVERHEAD; + utxo_size_inc -= prevout_size; + utxo_size_inc_actual -= prevout_size; } CAmount txfee = tx_total_in - tx_total_out; @@ -1940,6 +1961,8 @@ static RPCHelpMan getblockstats() ret_all.pushKV("txs", (int64_t)block.vtx.size()); ret_all.pushKV("utxo_increase", outputs - inputs); ret_all.pushKV("utxo_size_inc", utxo_size_inc); + ret_all.pushKV("utxo_increase_actual", utxos - inputs); + ret_all.pushKV("utxo_size_inc_actual", utxo_size_inc_actual); if (do_all) { return ret_all; diff --git a/test/functional/data/rpc_getblockstats.json b/test/functional/data/rpc_getblockstats.json index 16dbc5fe601..487945dd9fa 100644 --- a/test/functional/data/rpc_getblockstats.json +++ b/test/functional/data/rpc_getblockstats.json @@ -142,7 +142,9 @@ "totalfee": 0, "txs": 1, "utxo_increase": 2, - "utxo_size_inc": 163 + "utxo_increase_actual": 1, + "utxo_size_inc": 163, + "utxo_size_inc_actual": 75 }, { "avgfee": 4460, @@ -179,7 +181,9 @@ "totalfee": 4460, "txs": 2, "utxo_increase": 3, - "utxo_size_inc": 236 + "utxo_increase_actual": 2, + "utxo_size_inc": 236, + "utxo_size_inc_actual": 148 }, { "avgfee": 24906, @@ -216,7 +220,9 @@ "totalfee": 74720, "txs": 4, "utxo_increase": 5, - "utxo_size_inc": 384 + "utxo_size_inc": 384, + "utxo_increase_actual": 4, + "utxo_size_inc_actual": 296 } ] -} \ No newline at end of file +} diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py index 1ea1ee56596..1372cf95da4 100755 --- a/test/functional/rpc_getblockstats.py +++ b/test/functional/rpc_getblockstats.py @@ -161,6 +161,14 @@ class GetblockstatsTest(BitcoinTestFramework): 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") + assert_equal(genesis_stats["utxo_increase"], 1) + assert_equal(genesis_stats["utxo_size_inc"], 117) + assert_equal(genesis_stats["utxo_increase_actual"], 0) + assert_equal(genesis_stats["utxo_size_inc_actual"], 0) + if __name__ == '__main__': GetblockstatsTest().main() From ba9d288b2468f047e5a8e4637dd8749e247ff547 Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Sun, 11 Apr 2021 19:52:10 +0200 Subject: [PATCH 3/4] test: Fix getblockstats test data generator 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. --- test/functional/rpc_getblockstats.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py index 1372cf95da4..21fa4392f96 100755 --- a/test/functional/rpc_getblockstats.py +++ b/test/functional/rpc_getblockstats.py @@ -43,6 +43,10 @@ class GetblockstatsTest(BitcoinTestFramework): def generate_test_data(self, filename): mocktime = 1525107225 self.nodes[0].setmocktime(mocktime) + self.nodes[0].createwallet(wallet_name='test') + privkey = self.nodes[0].get_deterministic_priv_key().key + self.nodes[0].importprivkey(privkey) + self.generate(self.nodes[0], COINBASE_MATURITY + 1) address = self.nodes[0].get_deterministic_priv_key().address From d885bb2f6ea34cd21dacfebe763a07dbb389c1bd Mon Sep 17 00:00:00 2001 From: Fabian Jahr Date: Sun, 11 Apr 2021 20:46:25 +0200 Subject: [PATCH 4/4] test: Test exclusion of OP_RETURN from getblockstats --- test/functional/data/rpc_getblockstats.json | 88 ++++++++++----------- test/functional/rpc_getblockstats.py | 8 ++ 2 files changed, 52 insertions(+), 44 deletions(-) diff --git a/test/functional/data/rpc_getblockstats.json b/test/functional/data/rpc_getblockstats.json index 487945dd9fa..7d7460aacc8 100644 --- a/test/functional/data/rpc_getblockstats.json +++ b/test/functional/data/rpc_getblockstats.json @@ -102,8 +102,8 @@ "00000020f44e7a48b9f221af95f3295c8dcefc5358934a68dc79e2933dc0794b350cad0a90fad2cd50b41d4ef45e76c2a456b98c180632bb4b44e0cd18ce90679fe54e552b4ae75affff7f200000000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401630101ffffffff0200f2052a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000", "0000002087454276cce83f4d19e0120f6e9728ac5905f7adaf6b27e3f5bbe43ab823f85db7d1f44666531483df3d67c15f2c231718ad93b63b851dce5ff4c4a67f524ffa2b4ae75affff7f200100000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401640101ffffffff0200f2052a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000", "000000202cdc3e99f07a80252dd6097faa0eddf3f2dde5ae390610e0bca94ecc25931551d31fceb8fe0a682f6017ca3dbb582f3a2f06e5d99ec99c42c8a744dd4c9216b82b4ae75affff7f200300000001020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401650101ffffffff0200f2052a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ede2f61c3f71d1defd3fa999dfa36953755c690689799962b48bebd836974e8cf90120000000000000000000000000000000000000000000000000000000000000000000000000", - "000000209b3ace9bd510918d20e87518c0cf5976cab3e28cc7af41259a89c6dd7668a32922808b8a082be71bcd6152cb8fd223650b5579a41344ba749e4d17b9bf211a9e2b4ae75affff7f200000000002020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401660101ffffffff026c03062a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9edb85d8f3c122c43a72f1e0dd122c8f7af040aa0b0a46001621110fb37818021510120000000000000000000000000000000000000000000000000000000000000000000000000020000000128394022bf44bff30d7399cb5a16e3b94fed67dc174c2e1d77df91bad5a51cb3000000006a47304402201c16d06a5c4353168b3881071aea7d1eb4d88eedfea53a9d6af9abb56da9060002205abf3ae535f1f1b5cfe8ba955535c2b20ac003e7d7720c5b7d2640ac2a04d19001210227d85ba011276cf25b51df6a188b75e604b38770a462b2d0e9fb2fc839ef5d3ffeffffff0294b89a3b000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac00286bee0000000017a91452bab4f229415d0dc5c6d30b162f93a1a0cac5958765000000", - "000000200fa168b50a79ad24378a6b0f96e4c9f4ccb657a2663320d5fc1efd8ee7caa10ab42a31c444f2153387530a0979d4dc3dcc134b394c821227b8abff930c03c8412b4ae75affff7f200200000004020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401670101ffffffff02e015072a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ed20376d4bc90f9c689850eec3603cda658ba6295241730473ceb0e970b8d594150120000000000000000000000000000000000000000000000000000000000000000000000000020000000191e549a6cc852bbf1d3f11144b1a34079f64305e6971d2e685d2b40cd386e8a6000000006a47304402200bf62021c0a9a47ced8eba1e0998f5c71b2950763198d83ad284bd791241dbb00220446a05b7c35e7458924de88a8dcccab1ec6a106aa005345e55b482d8eb66337301210227d85ba011276cf25b51df6a188b75e604b38770a462b2d0e9fb2fc839ef5d3ffeffffff02acdbf405000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac94d7a4350000000017a914dfa6f0b17d2c64962c94203e744a9d4179ed22c18766000000020000000112d2f07672102dc6f099c4be308f598e4c4da1a7e0cb462ae14f0444525a1332000000006a47304402200a6a2f544f3f9d299608a7c745e2326de176fb1cac03ae3e74943f4250b8896e02205023a5b4faff99865bf91f1263605a502c723628be9240c0b7bec81d2ed106f101210227d85ba011276cf25b51df6a188b75e604b38770a462b2d0e9fb2fc839ef5d3ffeffffff0200ca9a3b000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac94166bee0000000017a914152cc82f7944f5c416de7dbffb052f7081765d7987660000000200000000010191e549a6cc852bbf1d3f11144b1a34079f64305e6971d2e685d2b40cd386e8a601000000171600147cc872ad7350c37fecab9c4c6d9f08aceb53bdb8feffffff02005ed0b20000000017a914aab1c8c53fe62e283a53efa28097709f4f2ed37b87e0bc9a3b000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0247304402201b4476f238ed5d515bfcd6927d0d008a4993770763eca73e3ee66f69971831d902200f5215a6dfd90391dd63462cfdf69804fe31224c309ec9c38d33a04dce71c0ee0121028c9d2955a95301b699db62e97d54bf0a91feb44e5cd94bbf5b62f1df57fb643966000000" + "000000209b3ace9bd510918d20e87518c0cf5976cab3e28cc7af41259a89c6dd7668a329f03ef4716ad5d88bccfd71088bf2ec3eb5b32e0ff60f35f9becd73052bfa8af12b4ae75affff7f200000000002020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401660101ffffffff025803062a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9edb11910e4e0ee6ee6d6bad42736999d1eba649243dc781438e5ef845c7227aaad0120000000000000000000000000000000000000000000000000000000000000000000000000020000000128394022bf44bff30d7399cb5a16e3b94fed67dc174c2e1d77df91bad5a51cb3000000006a47304402200650c6c50bd4952ca13b7aa37d458a36628434bbb968701063cdd36d0725e36c02202e059ccf7a4a049de028c4f140e543baa7e69ea3663e3d1fdfbc8ba7247e82f901210227d85ba011276cf25b51df6a188b75e604b38770a462b2d0e9fb2fc839ef5d3ffeffffff02a8b89a3b000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac00286bee0000000016001423838e991caedd69289d9dac88ca423cca683a2265000000", + "0000002061597bf3305ee2334b5d7fec136c2064b69d14955b50cd0b81f49ac33d88e506d80731ce60c2f275d29539a4d04c7e8c72aa4ade3c9baec24881a581fc524c6a2b4ae75affff7f200000000005020000000001010000000000000000000000000000000000000000000000000000000000000000ffffffff0401670101ffffffff023840072a010000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac0000000000000000266a24aa21a9ed89a3c65f40921b14168368cf4775a710ad17b613cedcff001f1f1ca3c863cc11012000000000000000000000000000000000000000000000000000000000000000000000000002000000000101bb475ac72ba1a45a96be584a689d6d0ace820d9587b0db53dc40a15555b9be770100000000feffffff02c0be9a3b000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88ac005ed0b200000000160014a57f6871c70569e0543322614c5c85438b796a900247304402207893b5466cdbf9cdedcc73fb8e10e01c4dd9aac4345031ef0c35d91e82ff5fd602207f0e1d7e4270a532060fd1e6ad7881d18acb173fd4fd1d61f3c8ff6707bdb972012103bb4c79ca594b19bbec7ee6302af0ef4191345fa7f03a30ed4e042aeed680924b6600000002000000000101e6a996cbac10b2d6b2bb2796a4ebf639ee21b136e06c7d8c6bc62b7cb4a311870100000000feffffff0200ca9a3b000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88acc088357700000000160014c48ea35298422796eb75ee9a04ebada66780083902473044022062963ff9f1f0d2c885060c083b97ddd67bd6e8a7daaed6578a62c1f905fd31a6022001836efe75bbce64d29700f5568aed78ce68f098ef0b8efdad0679e2f6c0ceb5012102228c4d459ce647b63b2681597a6e8391e4b5afab147f90747184a0893e4934c26600000002000000000101c654a35d86b4c3112ae9ec75e3bc271e0b8f928620386fdaf9517e8a9b511d850100000000feffffff024038f505000000001976a9142b4569203694fc997e13f2c0a1383b9e16c77a0d88acc0a73f7100000000160014cb1049e20cebfe756d657af0d47a3357c1db3c9702473044022024728eb27e884d08b2b95e670fd58c0e10106a18bc9e01f753f9ae474aa2c95e02201d5abe91302b373507dce1fd2f4b95ddc36e21d23eda6c476cc9efea80338ef90121036be02fd68622ce6740f0d028059af96a310c23c675f044732171df6f64f0fcb2660000000200000000010135c4ee1a780d8279ea7c79d3ad6fbb39315a13e6b51dd51f49db6e2f4796bada0100000000feffffff020000000000000000036a0121c8183f71000000001600147ea4d830ca77c20a23155a176a1472613dc4e7840247304402202db3527431e09ca8034d207134d79fc063939bd402286dd8b3872de3b2a746b402207faae5fb8838e6877822a9209fe2e81d4be4a69ce8164215e03f9b92d75e94f90121024d456d37df6f3436ee1685b78d90d2d24c4dd8c602d5f41405fe7f449b43415f00000000" ], "mocktime": 1525107225, "stats": [ @@ -147,10 +147,10 @@ "utxo_size_inc_actual": 75 }, { - "avgfee": 4460, + "avgfee": 4440, "avgfeerate": 20, - "avgtxsize": 223, - "blockhash": "0aa1cae78efd1efcd5203366a257b6ccf4c9e4960f6b8a3724ad790ab568a10f", + "avgtxsize": 222, + "blockhash": "06e5883dc39af4810bcd505b95149db664206c13ec7f5d4b33e25e30f37b5961", "feerate_percentiles": [ 20, 20, @@ -160,69 +160,69 @@ ], "height": 102, "ins": 1, - "maxfee": 4460, + "maxfee": 4440, "maxfeerate": 20, - "maxtxsize": 223, - "medianfee": 4460, + "maxtxsize": 222, + "medianfee": 4440, "mediantime": 1525107242, - "mediantxsize": 223, - "minfee": 4460, + "mediantxsize": 222, + "minfee": 4440, "minfeerate": 20, - "mintxsize": 223, + "mintxsize": 222, "outs": 4, "subsidy": 5000000000, "swtotal_size": 0, "swtotal_weight": 0, "swtxs": 0, "time": 1525107243, - "total_out": 4999995540, - "total_size": 223, - "total_weight": 892, - "totalfee": 4460, + "total_out": 4999995560, + "total_size": 222, + "total_weight": 888, + "totalfee": 4440, "txs": 2, "utxo_increase": 3, "utxo_increase_actual": 2, - "utxo_size_inc": 236, - "utxo_size_inc_actual": 148 + "utxo_size_inc": 235, + "utxo_size_inc_actual": 147 }, { - "avgfee": 24906, - "avgfeerate": 121, - "avgtxsize": 231, - "blockhash": "53e416e2538bc783c42a7aea566e884321afed893e9e58cf356d6429759dfa46", + "avgfee": 21390, + "avgfeerate": 155, + "avgtxsize": 219, + "blockhash": "7474991c2ae3c94c4813d75b4c752028304b773dd4dce8d460dfa2d1e7b542a3", "feerate_percentiles": [ 20, 20, 20, - 300, - 300 + 301, + 301 ], "height": 103, - "ins": 3, - "maxfee": 66900, - "maxfeerate": 300, - "maxtxsize": 249, - "medianfee": 4460, + "ins": 4, + "maxfee": 43200, + "maxfeerate": 301, + "maxtxsize": 225, + "medianfee": 19740, "mediantime": 1525107243, - "mediantxsize": 223, - "minfee": 3360, + "mediantxsize": 225, + "minfee": 2880, "minfeerate": 20, - "mintxsize": 223, - "outs": 8, + "mintxsize": 203, + "outs": 10, "subsidy": 5000000000, - "swtotal_size": 249, - "swtotal_weight": 669, - "swtxs": 1, + "swtotal_size": 878, + "swtotal_weight": 2204, + "swtxs": 4, "time": 1525107243, - "total_out": 9999920820, - "total_size": 695, - "total_weight": 2453, - "totalfee": 74720, - "txs": 4, - "utxo_increase": 5, - "utxo_size_inc": 384, + "total_out": 10899908680, + "total_size": 878, + "total_weight": 2204, + "totalfee": 85560, + "txs": 5, + "utxo_increase": 6, "utxo_increase_actual": 4, - "utxo_size_inc_actual": 296 + "utxo_size_inc": 441, + "utxo_size_inc_actual": 300 } ] -} +} \ No newline at end of file diff --git a/test/functional/rpc_getblockstats.py b/test/functional/rpc_getblockstats.py index 21fa4392f96..bf261befcc8 100755 --- a/test/functional/rpc_getblockstats.py +++ b/test/functional/rpc_getblockstats.py @@ -57,6 +57,8 @@ class GetblockstatsTest(BitcoinTestFramework): self.nodes[0].sendtoaddress(address=address, amount=10, subtractfeefromamount=False) self.nodes[0].settxfee(amount=0.003) self.nodes[0].sendtoaddress(address=address, amount=1, subtractfeefromamount=True) + # Send to OP_RETURN output to test its exclusion from statistics + self.nodes[0].send(outputs={"data": "21"}) self.sync_all() self.generate(self.nodes[0], 1) @@ -173,6 +175,12 @@ class GetblockstatsTest(BitcoinTestFramework): assert_equal(genesis_stats["utxo_increase_actual"], 0) assert_equal(genesis_stats["utxo_size_inc_actual"], 0) + self.log.info('Test tip including OP_RETURN') + 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) + assert_equal(tip_stats["utxo_size_inc_actual"], 300) if __name__ == '__main__': GetblockstatsTest().main()