mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-09-11 21:20:39 +02:00
rpc: add fee_rate_estimator option to estimatesmartfee
Add a string fee_rate_estimator option (default "none") to estimatesmartfee options. "block_policy" consults only the block policy fee rate estimator, "none" uses the fee rate estimator manager selected behaviour, and unknown values are treated as "none". Unknown option keys are rejected. Still only the block policy fee rate estimator, so the result is unchanged; a subsequent commit will change the default behaviour. Also adds GetFeeRateEstimate(FeeRateEstimatorType, target, conservative) to FeeRateEstimatorManager so callers can query a single estimator by type; NONE returns the manager-selected combined estimate.
This commit is contained in:
@@ -92,7 +92,7 @@ def check_smart_estimates(node, fees_seen):
|
||||
"""Call estimatesmartfee and verify that the estimates meet certain invariants."""
|
||||
|
||||
delta = 1.0e-6 # account for rounding error
|
||||
all_smart_estimates = [node.estimatesmartfee(i) for i in range(1, 26)]
|
||||
all_smart_estimates = [node.estimatesmartfee(i, "economical", {"fee_rate_estimator": "block_policy"}) for i in range(1, 26)]
|
||||
mempoolMinFee = node.getmempoolinfo()["mempoolminfee"]
|
||||
minRelaytxFee = node.getmempoolinfo()["minrelaytxfee"]
|
||||
feerate_ceiling = max(max(fees_seen), float(mempoolMinFee), float(minRelaytxFee))
|
||||
@@ -132,9 +132,10 @@ def make_tx(wallet, utxo, feerate):
|
||||
)
|
||||
|
||||
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']
|
||||
fee_est_conservative = node.estimatesmartfee(1, "conservative", {"fee_rate_estimator": "block_policy"})['feerate']
|
||||
fee_est_economical = node.estimatesmartfee(1, "economical", {"fee_rate_estimator": "block_policy"})['feerate']
|
||||
# Omit estimate_mode to check that the default mode is economical.
|
||||
fee_est_default = node.estimatesmartfee(1, options={"fee_rate_estimator": "block_policy"})['feerate']
|
||||
assert_equal(fee_est_conservative, expected_conservative)
|
||||
assert_equal(fee_est_economical, expected_economical)
|
||||
assert_equal(fee_est_default, expected_economical)
|
||||
@@ -244,7 +245,7 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
check_estimates(self.nodes[1], self.fees_per_kb)
|
||||
|
||||
def test_estimates_with_highminrelaytxfee(self):
|
||||
high_val = 3 * self.nodes[1].estimatesmartfee(2)["feerate"]
|
||||
high_val = 3 * self.nodes[1].estimatesmartfee(2, "economical", {"fee_rate_estimator": "block_policy"})["feerate"]
|
||||
self.restart_node(1, extra_args=[f"-minrelaytxfee={high_val}"])
|
||||
check_smart_estimates(self.nodes[1], self.fees_per_kb)
|
||||
self.restart_node(1)
|
||||
@@ -309,16 +310,16 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
# Only 10% of the transactions were really confirmed with a low feerate,
|
||||
# the rest needed to be RBF'd. We must return the 90% conf rate feerate.
|
||||
high_feerate_kvb = Decimal(high_feerate) / COIN * 10 ** 3
|
||||
est_feerate = node.estimatesmartfee(2)["feerate"]
|
||||
est_feerate = node.estimatesmartfee(2, "economical", {"fee_rate_estimator": "block_policy"})["feerate"]
|
||||
assert_equal(est_feerate, high_feerate_kvb)
|
||||
|
||||
def test_old_fee_estimate_file(self):
|
||||
# Get the initial fee rate while node is running
|
||||
fee_rate = self.nodes[0].estimatesmartfee(1)["feerate"]
|
||||
fee_rate = self.nodes[0].estimatesmartfee(1, "economical", {"fee_rate_estimator": "block_policy"})["feerate"]
|
||||
|
||||
# Restart node to ensure fee_estimate.dat file is read
|
||||
self.restart_node(0)
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1)["feerate"], fee_rate)
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1, "economical", {"fee_rate_estimator": "block_policy"})["feerate"], fee_rate)
|
||||
|
||||
fee_dat = self.nodes[0].chain_path / "fee_estimates.dat"
|
||||
|
||||
@@ -329,7 +330,7 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
|
||||
# Start node and ensure the fee_estimates.dat file was not read
|
||||
self.start_node(0)
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1)["errors"], ["Insufficient data or no feerate found"])
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1, "economical", {"fee_rate_estimator": "block_policy"})["errors"], ["Insufficient data or no feerate found"])
|
||||
|
||||
|
||||
def test_estimate_dat_is_flushed_periodically(self):
|
||||
@@ -387,7 +388,7 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
|
||||
def test_acceptstalefeeestimates_option(self):
|
||||
# Get the initial fee rate while node is running
|
||||
fee_rate = self.nodes[0].estimatesmartfee(1)["feerate"]
|
||||
fee_rate = self.nodes[0].estimatesmartfee(1, "economical", {"fee_rate_estimator": "block_policy"})["feerate"]
|
||||
|
||||
self.stop_node(0)
|
||||
|
||||
@@ -399,7 +400,7 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
|
||||
# Restart node with -acceptstalefeeestimates option to ensure fee_estimate.dat file is read
|
||||
self.start_node(0,extra_args=["-acceptstalefeeestimates"])
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1)["feerate"], fee_rate)
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1, "economical", {"fee_rate_estimator": "block_policy"})["feerate"], fee_rate)
|
||||
|
||||
def clear_estimates(self):
|
||||
self.log.info("Restarting node with fresh estimation")
|
||||
@@ -410,7 +411,7 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
self.connect_nodes(0, 1)
|
||||
self.connect_nodes(0, 2)
|
||||
self.sync_blocks()
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1)["errors"], ["Insufficient data or no feerate found"])
|
||||
assert_equal(self.nodes[0].estimatesmartfee(1, "economical", {"fee_rate_estimator": "block_policy"})["errors"], ["Insufficient data or no feerate found"])
|
||||
|
||||
def broadcast_many(self, broadcaster, feerate, count, miner=None):
|
||||
"""Broadcast and maybe mine some number of transactions with a specified fee rate."""
|
||||
@@ -451,8 +452,7 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
for i in range(6):
|
||||
self.broadcast_many(self.nodes[1], feerate_0_5_s_per_vb, TXS_COUNT)
|
||||
self.broadcast_many(self.nodes[1], feerate_1_s_per_vb, TXS_COUNT, self.nodes[2])
|
||||
assert_equal(feerate_0_5_s_per_vb, self.nodes[0].estimatesmartfee(1)["feerate"])
|
||||
|
||||
assert_equal(feerate_0_5_s_per_vb, self.nodes[0].estimatesmartfee(1, "economical", {"fee_rate_estimator": "block_policy"})["feerate"])
|
||||
|
||||
def run_test(self):
|
||||
self.log.info("This test is time consuming, please be patient")
|
||||
|
||||
@@ -28,12 +28,16 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
assert_raises_rpc_error(-3, "JSON value of type string is not of expected type number", self.nodes[0].estimaterawfee, 'foo')
|
||||
# wrong type for estimatesmartfee(estimate_mode)
|
||||
assert_raises_rpc_error(-3, "JSON value of type number is not of expected type string", self.nodes[0].estimatesmartfee, 1, 1)
|
||||
# wrong type for estimatesmartfee(options.fee_rate_estimator)
|
||||
assert_raises_rpc_error(-3, "JSON value of type number for field fee_rate_estimator is not of expected type string", self.nodes[0].estimatesmartfee, 1, 'ECONOMICAL', {'fee_rate_estimator': 1})
|
||||
# wrong type for estimaterawfee(threshold)
|
||||
assert_raises_rpc_error(-3, "JSON value of type string is not of expected type number", self.nodes[0].estimaterawfee, 1, 'foo')
|
||||
|
||||
assert_raises_rpc_error(-8, 'Invalid estimate_mode parameter, must be one of: "unset", "economical", "conservative"', self.nodes[0].estimatesmartfee, 1, 'foo')
|
||||
assert_raises_rpc_error(-8, "Unknown named parameter fee_rate_estimator", self.nodes[0].estimatesmartfee, 1, fee_rate_estimator=True)
|
||||
assert_raises_rpc_error(-3, "Unexpected key block_policy_only", self.nodes[0].estimatesmartfee, 1, 'ECONOMICAL', {'block_policy_only': True})
|
||||
# extra params
|
||||
assert_raises_rpc_error(-1, "estimatesmartfee", self.nodes[0].estimatesmartfee, 1, 'ECONOMICAL', 1)
|
||||
assert_raises_rpc_error(-1, "estimatesmartfee", self.nodes[0].estimatesmartfee, 1, 'ECONOMICAL', {}, 1)
|
||||
assert_raises_rpc_error(-1, "estimaterawfee", self.nodes[0].estimaterawfee, 1, 1, 1)
|
||||
|
||||
# max value of 1008 per src/policy/fees/block_policy_estimator.h
|
||||
@@ -45,6 +49,8 @@ class EstimateFeeTest(BitcoinTestFramework):
|
||||
self.nodes[0].estimatesmartfee(1, 'ECONOMICAL')
|
||||
self.nodes[0].estimatesmartfee(1, 'unset')
|
||||
self.nodes[0].estimatesmartfee(1, 'conservative')
|
||||
self.nodes[0].estimatesmartfee(1, 'ECONOMICAL', {"fee_rate_estimator": "block_policy"})
|
||||
self.nodes[0].estimatesmartfee(1, 'ECONOMICAL', {"fee_rate_estimator": "foo"})
|
||||
|
||||
self.nodes[0].estimaterawfee(1)
|
||||
self.nodes[0].estimaterawfee(1, None)
|
||||
|
||||
Reference in New Issue
Block a user