reth_rpc/eth/
builder.rs

1//! `EthApiBuilder` implementation
2
3use crate::{
4    eth::{core::EthApiInner, EthTxBuilder},
5    EthApi,
6};
7use reth_chain_state::CanonStateSubscriptions;
8use reth_chainspec::ChainSpecProvider;
9use reth_node_api::NodePrimitives;
10use reth_rpc_eth_types::{
11    fee_history::fee_history_cache_new_blocks_task, EthStateCache, EthStateCacheConfig,
12    FeeHistoryCache, FeeHistoryCacheConfig, GasCap, GasPriceOracle, GasPriceOracleConfig,
13};
14use reth_rpc_server_types::constants::{
15    DEFAULT_ETH_PROOF_WINDOW, DEFAULT_MAX_SIMULATE_BLOCKS, DEFAULT_PROOF_PERMITS,
16};
17use reth_storage_api::{BlockReaderIdExt, StateProviderFactory};
18use reth_tasks::{pool::BlockingTaskPool, TaskSpawner, TokioTaskExecutor};
19use std::sync::Arc;
20
21/// A helper to build the `EthApi` handler instance.
22///
23/// This builder type contains all settings to create an [`EthApiInner`] or an [`EthApi`] instance
24/// directly.
25#[derive(Debug)]
26pub struct EthApiBuilder<Provider, Pool, Network, EvmConfig>
27where
28    Provider: BlockReaderIdExt,
29{
30    provider: Provider,
31    pool: Pool,
32    network: Network,
33    evm_config: EvmConfig,
34    gas_cap: GasCap,
35    max_simulate_blocks: u64,
36    eth_proof_window: u64,
37    fee_history_cache_config: FeeHistoryCacheConfig,
38    proof_permits: usize,
39    eth_state_cache_config: EthStateCacheConfig,
40    eth_cache: Option<EthStateCache<Provider::Block, Provider::Receipt>>,
41    gas_oracle_config: GasPriceOracleConfig,
42    gas_oracle: Option<GasPriceOracle<Provider>>,
43    blocking_task_pool: Option<BlockingTaskPool>,
44    task_spawner: Box<dyn TaskSpawner + 'static>,
45}
46
47impl<Provider, Pool, Network, EvmConfig> EthApiBuilder<Provider, Pool, Network, EvmConfig>
48where
49    Provider: BlockReaderIdExt,
50{
51    /// Creates a new `EthApiBuilder` instance.
52    pub fn new(provider: Provider, pool: Pool, network: Network, evm_config: EvmConfig) -> Self
53    where
54        Provider: BlockReaderIdExt,
55    {
56        Self {
57            provider,
58            pool,
59            network,
60            evm_config,
61            eth_cache: None,
62            gas_oracle: None,
63            gas_cap: GasCap::default(),
64            max_simulate_blocks: DEFAULT_MAX_SIMULATE_BLOCKS,
65            eth_proof_window: DEFAULT_ETH_PROOF_WINDOW,
66            blocking_task_pool: None,
67            fee_history_cache_config: FeeHistoryCacheConfig::default(),
68            proof_permits: DEFAULT_PROOF_PERMITS,
69            task_spawner: TokioTaskExecutor::default().boxed(),
70            gas_oracle_config: Default::default(),
71            eth_state_cache_config: Default::default(),
72        }
73    }
74
75    /// Configures the task spawner used to spawn additional tasks.
76    pub fn task_spawner(mut self, spawner: impl TaskSpawner + 'static) -> Self {
77        self.task_spawner = Box::new(spawner);
78        self
79    }
80
81    /// Sets `eth_cache` config for the cache that will be used if no [`EthStateCache`] is
82    /// configured.
83    pub const fn eth_state_cache_config(
84        mut self,
85        eth_state_cache_config: EthStateCacheConfig,
86    ) -> Self {
87        self.eth_state_cache_config = eth_state_cache_config;
88        self
89    }
90
91    /// Sets `eth_cache` instance
92    pub fn eth_cache(
93        mut self,
94        eth_cache: EthStateCache<Provider::Block, Provider::Receipt>,
95    ) -> Self {
96        self.eth_cache = Some(eth_cache);
97        self
98    }
99
100    /// Sets `gas_oracle` config for the gas oracle that will be used if no [`GasPriceOracle`] is
101    /// configured.
102    pub const fn gas_oracle_config(mut self, gas_oracle_config: GasPriceOracleConfig) -> Self {
103        self.gas_oracle_config = gas_oracle_config;
104        self
105    }
106
107    /// Sets `gas_oracle` instance
108    pub fn gas_oracle(mut self, gas_oracle: GasPriceOracle<Provider>) -> Self {
109        self.gas_oracle = Some(gas_oracle);
110        self
111    }
112
113    /// Sets the gas cap.
114    pub const fn gas_cap(mut self, gas_cap: GasCap) -> Self {
115        self.gas_cap = gas_cap;
116        self
117    }
118
119    /// Sets the maximum number of blocks for `eth_simulateV1`.
120    pub const fn max_simulate_blocks(mut self, max_simulate_blocks: u64) -> Self {
121        self.max_simulate_blocks = max_simulate_blocks;
122        self
123    }
124
125    /// Sets the maximum number of blocks into the past for generating state proofs.
126    pub const fn eth_proof_window(mut self, eth_proof_window: u64) -> Self {
127        self.eth_proof_window = eth_proof_window;
128        self
129    }
130
131    /// Sets the blocking task pool.
132    pub fn blocking_task_pool(mut self, blocking_task_pool: BlockingTaskPool) -> Self {
133        self.blocking_task_pool = Some(blocking_task_pool);
134        self
135    }
136
137    /// Sets the fee history cache.
138    pub const fn fee_history_cache_config(
139        mut self,
140        fee_history_cache_config: FeeHistoryCacheConfig,
141    ) -> Self {
142        self.fee_history_cache_config = fee_history_cache_config;
143        self
144    }
145
146    /// Sets the proof permits.
147    pub const fn proof_permits(mut self, proof_permits: usize) -> Self {
148        self.proof_permits = proof_permits;
149        self
150    }
151
152    /// Builds the [`EthApiInner`] instance.
153    ///
154    /// If not configured, this will spawn the cache backend: [`EthStateCache::spawn`].
155    ///
156    /// # Panics
157    ///
158    /// This function panics if the blocking task pool cannot be built.
159    /// This will panic if called outside the context of a Tokio runtime.
160    pub fn build_inner(self) -> EthApiInner<Provider, Pool, Network, EvmConfig>
161    where
162        Provider: BlockReaderIdExt
163            + StateProviderFactory
164            + ChainSpecProvider
165            + CanonStateSubscriptions<
166                Primitives: NodePrimitives<Block = Provider::Block, Receipt = Provider::Receipt>,
167            > + Clone
168            + Unpin
169            + 'static,
170    {
171        let Self {
172            provider,
173            pool,
174            network,
175            evm_config,
176            eth_state_cache_config,
177            gas_oracle_config,
178            eth_cache,
179            gas_oracle,
180            gas_cap,
181            max_simulate_blocks,
182            eth_proof_window,
183            blocking_task_pool,
184            fee_history_cache_config,
185            proof_permits,
186            task_spawner,
187        } = self;
188
189        let eth_cache = eth_cache
190            .unwrap_or_else(|| EthStateCache::spawn(provider.clone(), eth_state_cache_config));
191        let gas_oracle = gas_oracle.unwrap_or_else(|| {
192            GasPriceOracle::new(provider.clone(), gas_oracle_config, eth_cache.clone())
193        });
194        let fee_history_cache = FeeHistoryCache::new(fee_history_cache_config);
195        let new_canonical_blocks = provider.canonical_state_stream();
196        let fhc = fee_history_cache.clone();
197        let cache = eth_cache.clone();
198        let prov = provider.clone();
199        task_spawner.spawn_critical(
200            "cache canonical blocks for fee history task",
201            Box::pin(async move {
202                fee_history_cache_new_blocks_task(fhc, new_canonical_blocks, prov, cache).await;
203            }),
204        );
205
206        EthApiInner::new(
207            provider,
208            pool,
209            network,
210            eth_cache,
211            gas_oracle,
212            gas_cap,
213            max_simulate_blocks,
214            eth_proof_window,
215            blocking_task_pool.unwrap_or_else(|| {
216                BlockingTaskPool::build().expect("failed to build blocking task pool")
217            }),
218            fee_history_cache,
219            evm_config,
220            task_spawner,
221            proof_permits,
222        )
223    }
224
225    /// Builds the [`EthApi`] instance.
226    ///
227    /// If not configured, this will spawn the cache backend: [`EthStateCache::spawn`].
228    ///
229    /// # Panics
230    ///
231    /// This function panics if the blocking task pool cannot be built.
232    /// This will panic if called outside the context of a Tokio runtime.
233    pub fn build(self) -> EthApi<Provider, Pool, Network, EvmConfig>
234    where
235        Provider: BlockReaderIdExt
236            + StateProviderFactory
237            + CanonStateSubscriptions<
238                Primitives: NodePrimitives<Block = Provider::Block, Receipt = Provider::Receipt>,
239            > + ChainSpecProvider
240            + Clone
241            + Unpin
242            + 'static,
243    {
244        EthApi { inner: Arc::new(self.build_inner()), tx_resp_builder: EthTxBuilder }
245    }
246}