# Bitcoin Core ASAP (1,2) Fee Estimation Design Document
## 1. Introduction
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 forecasting strategies and performs mempool health checks to determine the most appropriate strategy for providing fee rate estimates. This approach facilitates the addition of new estimation methods while ensuring smooth integration with existing systems.
## 2. Design Overview
The system is organized into two primary components:
- **ForecasterManager**: Manages multiple fee estimation strategies, coordinates between them, and interfaces with RPCs and wallets.
- **Forecaster**: Defines the interface for all fee estimation strategies, ensuring consistency and extensibility.
## 3. ForecasterManager
The `ForecasterManager` is responsible for aggregating fee estimates from various forecasters and selecting the optimal estimate. It maintains shared pointers to each registered forecaster and subscribes to validation interface notifications for performing mempool health checks.
```mermaid
classDiagram
class ForecasterManager {
+map<ForecastType, std::shared_ptr<Forecaster>> forecasters
+CBlockPolicyEstimator* GetBlockPolicyEstimator()
+void RegisterForecaster(std::shared_ptr<Forecaster>)
+ForecastResult GetFeeRateEstimateFromForecasters(ConfirmationTarget target)
}
class Forecaster {
+ForecastType m_forecastType
+virtual ForecastResult EstimateFeeFee(ConfirmationTarget target)*
}
class CValidationInterface {
+void MempoolTransactionsRemovedForBlock(...)
+void BlockConnected(...)
}
ForecasterManager --> Forecaster
ForecasterManager --> CValidationInterface
```
### Responsibilities
- **Registration**: Allows new forecasters to be registered.
- **Estimation Coordination**: Aggregates estimates from different forecasters and selects the best fee rate estimate.
- **Validation Interface Integration**: Listens to network events (block connections, mempool changes) to adjust the state of the mempool as blocks are connected.
## 4. Forecaster
The `Forecaster` abstract class specifies the interface that all fee estimation strategies must implement. This ensures that any new strategy integrates seamlessly into the system.
```mermaid
classDiagram
class Forecaster {
+ForecastType m_forecastType*
+virtual ForecastResult EstimateFeeFee(ConfirmationTarget target)*
}
```
### Definitions
- **ForecastType**: An enum to identify the type of forecaster.
- **EstimateFeeFee(ConfirmationTarget target)**: A pure virtual method that must be implemented by each derived class to provide fee rate estimates.
`ConfirmationTarget` is a struct that encapsulates:
- The type of confirmation target (block-based or time-based)
- The target value (e.g., number of blocks or hours)
- Additional metadata (e.g., transactions to exclude)
## 5. Forecaster Implementations
### 5.1. Mempool-Based Forecaster (`MemPoolForecaster`)
`MemPoolForecaster` derives from `Forecaster` and estimates fee rates by constructing block templates from the node’s mempool. It provides:
- **High-priority fee estimates**: Based on the 50th percentile mining score.
- **Low-priority fee estimates**: Based on the 75th percentile mining score.
It owns pointers to the mempool and chainstate for generating blocks templates.
```mermaid
classDiagram
class Forecaster {
+ForecastType m_forecastType
+virtual ForecastResult EstimateFeeFee(ConfirmationTarget target)*
}
class MemPoolForecaster {
+CTxMemPool* m_mempool
+Chainstate* m_chainstate
+ForecastResult EstimateFeeFee(ConfirmationTarget target) override
}
Forecaster <|-- MemPoolForecaster
```
### 5.2. Block Policy Estimator Forecaster
This forecaster integrates the existing `CBlockPolicyEstimator` by subclassing `Forecaster`. Its implementation of `EstimateFeeFee` acts as a wrapper around the `estimatesmartfee` function.
```mermaid
classDiagram
class Forecaster {
+ForecastType m_forecastType
+virtual ForecastResult EstimateFeeFee(ConfirmationTarget target)*
}
class BlockPolicyEstimator {
+ForecastResult EstimateFeeFee(ConfirmationTarget target) override
}
Forecaster <|-- BlockPolicyEstimator
```
## 6. Fee Estimation Flow
The flow below outlines how the system processes fee estimation requests:
```mermaid
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 estimateFeeRate]
F --> G[Return lowest estimate]
style A fill:#f9f,stroke:#333,stroke-width:2px;
style B fill:#ff9,stroke:#333,stroke-width:2px;
style C fill:#9f9,stroke:#333,stroke-width:2px;
style D fill:#f96,stroke:#333,stroke-width:2px;
style E fill:#9ff,stroke:#333,stroke-width:2px;
style F fill:#9f9,stroke:#333,stroke-width:2px;
style G fill:#ff9,stroke:#333,stroke-width:2px;
```
This flow is for ASAP fee rates estimate i.e 1–2 block targets.
For confirmation target > 2 `CBlockPolicyEstimator` will be used.
Transactions using this strategy are recommended to be RBF-enabled to allow fee bumping.
## 7. Next Steps
- Integrate the `ForecasterManager` with wallet functionality to enable dynamic fee estimation during transaction creation.
- Continue refining estimation algorithms based on empirical network data and testing.
## 8. FAQ
### 8.1. Can miners manipulate fee estimates by broadcasting and replacing high-fee transactions?
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.
### 8.2. What happens if `CBlockPolicyEstimator` provides a lower estimate during congestion?
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.
### 8.3. How does `MemPoolForecaster` avoid excessive block template generation?
`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](https://bitcoin.stackexchange.com/questions/125776/how-long-does-it-take-for-a-transaction-to-propagate-through-the-network), this interval is sufficient to reduce overhead.
---
This design document outlines a clean and modular approach to fee estimation in Bitcoin Core. The structured integration of multiple forecasters under the management of `ForecasterManager` ensures that the system remains adaptable and maintains high estimation accuracy while accommodating future enhancements.