diff options
author | merge-script <fanquake@gmail.com> | 2024-07-25 10:44:50 +0100 |
---|---|---|
committer | merge-script <fanquake@gmail.com> | 2024-07-25 10:44:50 +0100 |
commit | f7ab3ba404df15daf80986382f01f4e06f3b8791 (patch) | |
tree | 9e6510104fcc1c48d3c2edfbe20e7cf42507dcdc /test/functional/feature_fee_estimation.py | |
parent | 1ca1df9353b69b69c891f8adfce864e00da2a552 (diff) | |
parent | 25bf86a225b0df3f48ade1016b47f5ee1636b988 (diff) |
Merge bitcoin/bitcoin#30275: Fee Estimation: change `estimatesmartfee` default mode to `economical`
25bf86a225b0df3f48ade1016b47f5ee1636b988 [test]: ensure `estimatesmartfee` default mode is `economical` (ismaelsadeeq)
41a2545046bce315af697a3c6baf6e3fb2e824c2 [fees]: change `estimatesmartfee` default mode to `economical` (ismaelsadeeq)
Pull request description:
Fixes #30009
This PR changes the `estimatesmartfee` default mode to `economical`.
This was also suggested on IRC https://bitcoin-irc.chaincode.com/bitcoin-core-dev/2024-04-26#1021609
- `conservative` mode: This is the `estimatesmartfee` RPC mode which considers a longer history of blocks. It potentially returns a higher fee rate and is more likely to be sufficient for the desired target, but it is not as responsive to short-term drops in the prevailing fee market.
- `economical` mode: This is the `estimatesmartfee` RPC mode where estimates are potentially lower and more responsive to short-term drops in the prevailing fee market.
Since users are likely to use the default mode, this change will reduce overestimation for many users. The conservative mode remains available for those who wish to opt-in.
For an in-depth analysis of how significantly the `conservative` mode overestimates, see
https://delvingbitcoin.org/t/bitcoind-policy-estimator-modes-analysis/964.
ACKs for top commit:
instagibbs:
reACK https://github.com/bitcoin/bitcoin/pull/30275/commits/25bf86a225b0df3f48ade1016b47f5ee1636b988
glozow:
ACK 25bf86a225b0df3f48ade1016b47f5ee1636b988
willcl-ark:
ACK 25bf86a225b0df3f48ade1016b47f5ee1636b988
Tree-SHA512: 78ebda667eb9c8f87dcc2f0e6c14968bd1de30358dc77a13611b186fb8427ad97d9f537bad6e32e0a1aa477ccd8c64fee4d41e19308ef3cb184ff1664e6ba8a6
Diffstat (limited to 'test/functional/feature_fee_estimation.py')
-rwxr-xr-x | test/functional/feature_fee_estimation.py | 54 |
1 files changed, 47 insertions, 7 deletions
diff --git a/test/functional/feature_fee_estimation.py b/test/functional/feature_fee_estimation.py index 34fb3c5573..a3dcb7afda 100755 --- a/test/functional/feature_fee_estimation.py +++ b/test/functional/feature_fee_estimation.py @@ -128,6 +128,14 @@ def make_tx(wallet, utxo, feerate): fee_rate=Decimal(feerate * 1000) / COIN, ) +def check_fee_estimates_btw_modes(node, expected_conservative, expected_economical): + fee_est_conservative = node.estimatesmartfee(1, estimate_mode="conservative")['feerate'] + fee_est_economical = node.estimatesmartfee(1, estimate_mode="economical")['feerate'] + fee_est_default = node.estimatesmartfee(1)['feerate'] + assert_equal(fee_est_conservative, expected_conservative) + assert_equal(fee_est_economical, expected_economical) + assert_equal(fee_est_default, expected_economical) + class EstimateFeeTest(BitcoinTestFramework): def set_test_params(self): @@ -382,6 +390,40 @@ class EstimateFeeTest(BitcoinTestFramework): self.start_node(0,extra_args=["-acceptstalefeeestimates"]) assert_equal(self.nodes[0].estimatesmartfee(1)["feerate"], fee_rate) + def clear_estimates(self): + self.log.info("Restarting node with fresh estimation") + self.stop_node(0) + fee_dat = self.nodes[0].chain_path / "fee_estimates.dat" + os.remove(fee_dat) + self.start_node(0) + self.connect_nodes(0, 1) + self.connect_nodes(0, 2) + assert_equal(self.nodes[0].estimatesmartfee(1)["errors"], ["Insufficient data or no feerate found"]) + + def broadcast_and_mine(self, broadcaster, miner, feerate, count): + """Broadcast and mine some number of transactions with a specified fee rate.""" + for _ in range(count): + self.wallet.send_self_transfer(from_node=broadcaster, fee_rate=feerate) + self.sync_mempools() + self.generate(miner, 1) + + def test_estimation_modes(self): + low_feerate = Decimal("0.001") + high_feerate = Decimal("0.005") + tx_count = 24 + # Broadcast and mine high fee transactions for the first 12 blocks. + for _ in range(12): + self.broadcast_and_mine(self.nodes[1], self.nodes[2], high_feerate, tx_count) + check_fee_estimates_btw_modes(self.nodes[0], high_feerate, high_feerate) + + # We now track 12 blocks; short horizon stats will start decaying. + # Broadcast and mine low fee transactions for the next 4 blocks. + for _ in range(4): + self.broadcast_and_mine(self.nodes[1], self.nodes[2], low_feerate, tx_count) + # conservative mode will consider longer time horizons while economical mode does not + # Check the fee estimates for both modes after mining low fee transactions. + check_fee_estimates_btw_modes(self.nodes[0], high_feerate, low_feerate) + def run_test(self): self.log.info("This test is time consuming, please be patient") @@ -420,17 +462,15 @@ class EstimateFeeTest(BitcoinTestFramework): self.log.info("Test reading old fee_estimates.dat") self.test_old_fee_estimate_file() - self.log.info("Restarting node with fresh estimation") - self.stop_node(0) - fee_dat = os.path.join(self.nodes[0].chain_path, "fee_estimates.dat") - os.remove(fee_dat) - self.start_node(0) - self.connect_nodes(0, 1) - self.connect_nodes(0, 2) + self.clear_estimates() self.log.info("Testing estimates with RBF.") self.sanity_check_rbf_estimates(self.confutxo + self.memutxo) + self.clear_estimates() + self.log.info("Test estimatesmartfee modes") + self.test_estimation_modes() + self.log.info("Testing that fee estimation is disabled in blocksonly.") self.restart_node(0, ["-blocksonly"]) assert_raises_rpc_error( |