This document introduces a modular and extensible fee estimation system for Bitcoin Core. The design is centered around a fee rate forecasting manager that integrates multiple fee rate forecasting strategies and performs mempool health checks to determine the most appropriate strategy for providing fee rate forecast. This approach facilitates the additions of new strategies while ensuring smooth integration with existing systems.
The system is organized into two primary components:
- ForecasterManager: Manages multiple fee rate forecasters, coordinates between them, and interfaces with RPCs and wallets.
- Forecaster: Defines the interface for all fee rate forecasters, ensuring consistency and extensibility.
The ForecasterManager is responsible for aggregating fee rate forecasts from various forecasters and selecting the best at the moment. It maintains shared pointers to each registered forecaster and subscribes to validation interface notifications for performing mempool health checks and updating other forecasters.
classDiagram
class ForecasterManager {
+map<ForecastType, std::shared_ptr<Forecaster>> forecasters
+CBlockPolicyEstimator* GetBlockPolicyEstimator()
+void RegisterForecaster(std::shared_ptr<Forecaster>)
+ForecastResult ForecastFeeRateFromForecasters(int target, bool conservative)
}
class Forecaster {
+ForecastType m_forecastType
+virtual ForecastResult ForecastFeeRate(int target, bool conservative)*
}
class CValidationInterface {
+void MempoolTransactionsRemovedForBlock(...)
+void BlockConnected(...)
}
ForecasterManager --> Forecaster
ForecasterManager --> CValidationInterface
- Registration: Allows new forecasters to be registered.
- Coordination: Aggregates fee rate from different forecasters and selects the best fee rate.
- Validation Interface Integration: Listens to network events (block connections, mempool changes) to adjust the state of the mempool as blocks are connected and update block policy estimator.
The Forecaster abstract class specifies the interface that all forecasting strategies must implement. This ensures that any new strategy integrates seamlessly into the system.
classDiagram
class Forecaster {
+ForecastType m_forecastType*
+virtual ForecastResult ForecastFeeRate(int target, bool conservative)*
}
- ForecastType: An enum to identify the type of forecaster.
- ForecastFeeRate(int target, bool conservative): A pure virtual method that must be implemented by each derived class to provide fee rate forecast.
MemPoolForecaster derives from Forecaster and forecast fee rates by constructing block templates from the node’s mempool. It provides:
- Conservative fee rate: Based on the 50th percentile mining score.
- Economical: Based on the 75th percentile mining score.
It owns pointers to the mempool and chainstate for generating blocks templates.
classDiagram
class Forecaster {
+ForecastType m_forecastType
+virtual ForecastResult ForecastFeeRate(int target, bool conservative)*
}
class MemPoolForecaster {
+CTxMemPool* m_mempool
+Chainstate* m_chainstate
+ForecastResult ForecastFeeRate(int target, bool conservative) override
}
Forecaster <|-- MemPoolForecaster
This forecaster integrates the existing CBlockPolicyEstimator by subclassing Forecaster. Its implementation of ForecastFeeRate acts as a wrapper around the estimatesmartfee function.
classDiagram
class Forecaster {
+ForecastType m_forecastType
+virtual ForecastResult ForecastFeeRate(int target, bool conservative)*
}
class BlockPolicyEstimator {
+ForecastResult ForecastFeeRate(int target, bool conservative) override
}
Forecaster <|-- BlockPolicyEstimator
The flow below outlines how the system processes fee estimation requests:
graph TD;
A[User requests fee estimate] --> B[ForecasterManager receives request]
B --> C{Sanity checks}
C -->|Fail| D[Return error message]
C -->|Pass| E[Determine which forecaster to call]
E --> F[Call Forecaster and BlockPolicyEstimator ForecastFeeRate]
F --> G[Return lowest estimate]
This flow is for ASAP fee rates estimate i.e 1–2 block targets.
For confirmation target > 2 CBlockPolicyEstimator will be used.
Services using this new feature are strongly recommended to make there transactions RBF-opt in to allow for fee bumping.
- Integrate the
ForecasterManagerwith wallet functionality to enable dynamic fee estimation during transaction creation. - Continue refining estimation algorithms based on empirical network data and testing e.g when MEV come to pass; mempool will not be reliable for fee rate forecast.
The design mitigates this risk by ensuring that the mempool-based estimator does not spike fees instantly. If mempool estimates exceed those from the CBlockPolicyEstimator, the system returns the lower estimate to prevent manipulation.
In periods of congestion, if the mempool-based estimate increases while CBlockPolicyEstimator remains low, transactions may take longer to confirm. However, RBF-enabled transactions can be fee-bumped to accommodate network conditions. As congestion eases, estimates adjust dynamically.
MemPoolForecaster caches recent fee estimates and regenerates block templates only if the last estimate is older than 30 seconds. Considering that transaction propagation across the network typically takes about 15 seconds, this interval is sufficient to reduce overhead.