Files
bitcoin/test/functional/rpc_estimatefee.py
ismaelsadeeq c9bb3df29f fees: add MemPoolFeeRateEstimator class
Add MemPoolFeeRateEstimator, which calls Bitcoin Core's block
assembler with the mempool and chainstate to build a block template and
use its chunk fee rates for fee rate estimation.

Add CalculateMaxWeightPercentiles to return the 50th and 75th
percentile chunk feerates by cumulative block weight. If sparse,
EstimateFeeRate uses the higher of the minimum relay fee rate and the
current mempool minimum fee rate.

The 50th percentile is returned as the conservative estimate, and the
75th percentile as the economical estimate.

Wire MemPoolFeeRateEstimator into FeeRateEstimatorManager and add
FeeRateEstimatorType::MEMPOOL_POLICY for result attribution.

Add unit tests for the mempool fee rate estimator and fee estimator
string conversions, plus fuzz coverage for the string conversions.

Co-authored-by: willcl-ark <will@256k1.dev>
2026-08-20 15:15:03 +01:00

63 lines
3.4 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (c) 2018-present The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the estimatefee RPCs.
Test the following RPCs:
- estimatesmartfee
- estimaterawfee
"""
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_raises_rpc_error
class EstimateFeeTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
def run_test(self):
# missing required params
assert_raises_rpc_error(-1, "estimatesmartfee", self.nodes[0].estimatesmartfee)
assert_raises_rpc_error(-1, "estimaterawfee", self.nodes[0].estimaterawfee)
# cli handles wrong types differently
if not self.options.usecli:
# wrong type for conf_target
assert_raises_rpc_error(-3, "JSON value of type string is not of expected type number", self.nodes[0].estimatesmartfee, 'foo')
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, "estimaterawfee", self.nodes[0].estimaterawfee, 1, 1, 1)
# max value of 1008 per src/policy/fees/block_policy_estimator.h
assert_raises_rpc_error(-8, "Invalid conf_target, must be between 1 and 1008", self.nodes[0].estimaterawfee, 1009)
# valid calls
self.nodes[0].estimatesmartfee(1)
# self.nodes[0].estimatesmartfee(1, None)
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": "mempool_policy"})
self.nodes[0].estimatesmartfee(1, 'ECONOMICAL', {"fee_rate_estimator": "foo"})
self.nodes[0].estimaterawfee(1)
self.nodes[0].estimaterawfee(1, None)
self.nodes[0].estimaterawfee(1, 1)
if __name__ == '__main__':
EstimateFeeTest(__file__).main()