reth_rpc/eth/
builder.rs

1//! `EthApiBuilder` implementation
2
3use crate::{eth::core::EthApiInner, EthApi};
4use alloy_network::Ethereum;
5use reth_chain_state::CanonStateSubscriptions;
6use reth_chainspec::ChainSpecProvider;
7use reth_primitives_traits::HeaderTy;
8use reth_rpc_convert::{RpcConvert, RpcConverter};
9use reth_rpc_eth_api::{
10    helpers::pending_block::PendingEnvBuilder, node::RpcNodeCoreAdapter, RpcNodeCore,
11};
12use reth_rpc_eth_types::{
13    builder::config::PendingBlockKind, fee_history::fee_history_cache_new_blocks_task,
14    receipt::EthReceiptConverter, EthStateCache, EthStateCacheConfig, FeeHistoryCache,
15    FeeHistoryCacheConfig, ForwardConfig, GasCap, GasPriceOracle, GasPriceOracleConfig,
16};
17use reth_rpc_server_types::constants::{
18    DEFAULT_ETH_PROOF_WINDOW, DEFAULT_MAX_SIMULATE_BLOCKS, DEFAULT_PROOF_PERMITS,
19};
20use reth_tasks::{pool::BlockingTaskPool, TaskSpawner, TokioTaskExecutor};
21use std::{sync::Arc, time::Duration};
22
23/// A helper to build the `EthApi` handler instance.
24///
25/// This builder type contains all settings to create an [`EthApiInner`] or an [`EthApi`] instance
26/// directly.
27#[derive(Debug)]
28pub struct EthApiBuilder<N: RpcNodeCore, Rpc, NextEnv = ()> {
29    components: N,
30    rpc_converter: Rpc,
31    gas_cap: GasCap,
32    max_simulate_blocks: u64,
33    eth_proof_window: u64,
34    fee_history_cache_config: FeeHistoryCacheConfig,
35    proof_permits: usize,
36    eth_state_cache_config: EthStateCacheConfig,
37    eth_cache: Option<EthStateCache<N::Primitives>>,
38    gas_oracle_config: GasPriceOracleConfig,
39    gas_oracle: Option<GasPriceOracle<N::Provider>>,
40    blocking_task_pool: Option<BlockingTaskPool>,
41    task_spawner: Box<dyn TaskSpawner + 'static>,
42    next_env: NextEnv,
43    max_batch_size: usize,
44    pending_block_kind: PendingBlockKind,
45    raw_tx_forwarder: ForwardConfig,
46    send_raw_transaction_sync_timeout: Duration,
47}
48
49impl<Provider, Pool, Network, EvmConfig, ChainSpec>
50    EthApiBuilder<
51        RpcNodeCoreAdapter<Provider, Pool, Network, EvmConfig>,
52        RpcConverter<Ethereum, EvmConfig, EthReceiptConverter<ChainSpec>>,
53    >
54where
55    RpcNodeCoreAdapter<Provider, Pool, Network, EvmConfig>:
56        RpcNodeCore<Provider: ChainSpecProvider<ChainSpec = ChainSpec>, Evm = EvmConfig>,
57{
58    /// Creates a new `EthApiBuilder` instance.
59    pub fn new(provider: Provider, pool: Pool, network: Network, evm_config: EvmConfig) -> Self {
60        Self::new_with_components(RpcNodeCoreAdapter::new(provider, pool, network, evm_config))
61    }
62}
63
64impl<N: RpcNodeCore, Rpc, NextEnv> EthApiBuilder<N, Rpc, NextEnv> {
65    /// Apply a function to the builder
66    pub fn apply<F>(self, f: F) -> Self
67    where
68        F: FnOnce(Self) -> Self,
69    {
70        f(self)
71    }
72
73    /// Converts the RPC converter type of this builder
74    pub fn map_converter<F, R>(self, f: F) -> EthApiBuilder<N, R, NextEnv>
75    where
76        F: FnOnce(Rpc) -> R,
77    {
78        let Self {
79            components,
80            rpc_converter,
81            gas_cap,
82            max_simulate_blocks,
83            eth_proof_window,
84            fee_history_cache_config,
85            proof_permits,
86            eth_state_cache_config,
87            eth_cache,
88            gas_oracle_config,
89            gas_oracle,
90            blocking_task_pool,
91            task_spawner,
92            next_env,
93            max_batch_size,
94            pending_block_kind,
95            raw_tx_forwarder,
96            send_raw_transaction_sync_timeout,
97        } = self;
98        EthApiBuilder {
99            components,
100            rpc_converter: f(rpc_converter),
101            gas_cap,
102            max_simulate_blocks,
103            eth_proof_window,
104            fee_history_cache_config,
105            proof_permits,
106            eth_state_cache_config,
107            eth_cache,
108            gas_oracle_config,
109            gas_oracle,
110            blocking_task_pool,
111            task_spawner,
112            next_env,
113            max_batch_size,
114            pending_block_kind,
115            raw_tx_forwarder,
116            send_raw_transaction_sync_timeout,
117        }
118    }
119}
120
121impl<N, ChainSpec> EthApiBuilder<N, RpcConverter<Ethereum, N::Evm, EthReceiptConverter<ChainSpec>>>
122where
123    N: RpcNodeCore<Provider: ChainSpecProvider<ChainSpec = ChainSpec>>,
124{
125    /// Creates a new `EthApiBuilder` instance with the provided components.
126    pub fn new_with_components(components: N) -> Self {
127        let rpc_converter =
128            RpcConverter::new(EthReceiptConverter::new(components.provider().chain_spec()));
129        Self {
130            components,
131            rpc_converter,
132            eth_cache: None,
133            gas_oracle: None,
134            gas_cap: GasCap::default(),
135            max_simulate_blocks: DEFAULT_MAX_SIMULATE_BLOCKS,
136            eth_proof_window: DEFAULT_ETH_PROOF_WINDOW,
137            blocking_task_pool: None,
138            fee_history_cache_config: FeeHistoryCacheConfig::default(),
139            proof_permits: DEFAULT_PROOF_PERMITS,
140            task_spawner: TokioTaskExecutor::default().boxed(),
141            gas_oracle_config: Default::default(),
142            eth_state_cache_config: Default::default(),
143            next_env: Default::default(),
144            max_batch_size: 1,
145            pending_block_kind: PendingBlockKind::Full,
146            raw_tx_forwarder: ForwardConfig::default(),
147            send_raw_transaction_sync_timeout: Duration::from_secs(30),
148        }
149    }
150}
151
152impl<N, Rpc, NextEnv> EthApiBuilder<N, Rpc, NextEnv>
153where
154    N: RpcNodeCore,
155{
156    /// Configures the task spawner used to spawn additional tasks.
157    pub fn task_spawner(mut self, spawner: impl TaskSpawner + 'static) -> Self {
158        self.task_spawner = Box::new(spawner);
159        self
160    }
161
162    /// Changes the configured converter.
163    pub fn with_rpc_converter<RpcNew>(
164        self,
165        rpc_converter: RpcNew,
166    ) -> EthApiBuilder<N, RpcNew, NextEnv> {
167        let Self {
168            components,
169            rpc_converter: _,
170            gas_cap,
171            max_simulate_blocks,
172            eth_proof_window,
173            fee_history_cache_config,
174            proof_permits,
175            eth_state_cache_config,
176            eth_cache,
177            gas_oracle,
178            blocking_task_pool,
179            task_spawner,
180            gas_oracle_config,
181            next_env,
182            max_batch_size,
183            pending_block_kind,
184            raw_tx_forwarder,
185            send_raw_transaction_sync_timeout,
186        } = self;
187        EthApiBuilder {
188            components,
189            rpc_converter,
190            gas_cap,
191            max_simulate_blocks,
192            eth_proof_window,
193            fee_history_cache_config,
194            proof_permits,
195            eth_state_cache_config,
196            eth_cache,
197            gas_oracle,
198            blocking_task_pool,
199            task_spawner,
200            gas_oracle_config,
201            next_env,
202            max_batch_size,
203            pending_block_kind,
204            raw_tx_forwarder,
205            send_raw_transaction_sync_timeout,
206        }
207    }
208
209    /// Changes the configured pending environment builder.
210    pub fn with_pending_env_builder<NextEnvNew>(
211        self,
212        next_env: NextEnvNew,
213    ) -> EthApiBuilder<N, Rpc, NextEnvNew> {
214        let Self {
215            components,
216            rpc_converter,
217            gas_cap,
218            max_simulate_blocks,
219            eth_proof_window,
220            fee_history_cache_config,
221            proof_permits,
222            eth_state_cache_config,
223            eth_cache,
224            gas_oracle,
225            blocking_task_pool,
226            task_spawner,
227            gas_oracle_config,
228            next_env: _,
229            max_batch_size,
230            pending_block_kind,
231            raw_tx_forwarder,
232            send_raw_transaction_sync_timeout,
233        } = self;
234        EthApiBuilder {
235            components,
236            rpc_converter,
237            gas_cap,
238            max_simulate_blocks,
239            eth_proof_window,
240            fee_history_cache_config,
241            proof_permits,
242            eth_state_cache_config,
243            eth_cache,
244            gas_oracle,
245            blocking_task_pool,
246            task_spawner,
247            gas_oracle_config,
248            next_env,
249            max_batch_size,
250            pending_block_kind,
251            raw_tx_forwarder,
252            send_raw_transaction_sync_timeout,
253        }
254    }
255
256    /// Sets `eth_cache` config for the cache that will be used if no [`EthStateCache`] is
257    /// configured.
258    pub const fn eth_state_cache_config(
259        mut self,
260        eth_state_cache_config: EthStateCacheConfig,
261    ) -> Self {
262        self.eth_state_cache_config = eth_state_cache_config;
263        self
264    }
265
266    /// Sets `eth_cache` instance
267    pub fn eth_cache(mut self, eth_cache: EthStateCache<N::Primitives>) -> Self {
268        self.eth_cache = Some(eth_cache);
269        self
270    }
271
272    /// Sets `gas_oracle` config for the gas oracle that will be used if no [`GasPriceOracle`] is
273    /// configured.
274    pub const fn gas_oracle_config(mut self, gas_oracle_config: GasPriceOracleConfig) -> Self {
275        self.gas_oracle_config = gas_oracle_config;
276        self
277    }
278
279    /// Sets `gas_oracle` instance
280    pub fn gas_oracle(mut self, gas_oracle: GasPriceOracle<N::Provider>) -> Self {
281        self.gas_oracle = Some(gas_oracle);
282        self
283    }
284
285    /// Sets the gas cap.
286    pub const fn gas_cap(mut self, gas_cap: GasCap) -> Self {
287        self.gas_cap = gas_cap;
288        self
289    }
290
291    /// Sets the maximum number of blocks for `eth_simulateV1`.
292    pub const fn max_simulate_blocks(mut self, max_simulate_blocks: u64) -> Self {
293        self.max_simulate_blocks = max_simulate_blocks;
294        self
295    }
296
297    /// Sets the maximum number of blocks into the past for generating state proofs.
298    pub const fn eth_proof_window(mut self, eth_proof_window: u64) -> Self {
299        self.eth_proof_window = eth_proof_window;
300        self
301    }
302
303    /// Sets the blocking task pool.
304    pub fn blocking_task_pool(mut self, blocking_task_pool: BlockingTaskPool) -> Self {
305        self.blocking_task_pool = Some(blocking_task_pool);
306        self
307    }
308
309    /// Sets the fee history cache.
310    pub const fn fee_history_cache_config(
311        mut self,
312        fee_history_cache_config: FeeHistoryCacheConfig,
313    ) -> Self {
314        self.fee_history_cache_config = fee_history_cache_config;
315        self
316    }
317
318    /// Sets the proof permits.
319    pub const fn proof_permits(mut self, proof_permits: usize) -> Self {
320        self.proof_permits = proof_permits;
321        self
322    }
323
324    /// Sets the max batch size for batching transaction insertions.
325    pub const fn max_batch_size(mut self, max_batch_size: usize) -> Self {
326        self.max_batch_size = max_batch_size;
327        self
328    }
329
330    /// Sets the pending block kind
331    pub const fn pending_block_kind(mut self, pending_block_kind: PendingBlockKind) -> Self {
332        self.pending_block_kind = pending_block_kind;
333        self
334    }
335
336    /// Sets the raw transaction forwarder.
337    pub fn raw_tx_forwarder(mut self, tx_forwarder: ForwardConfig) -> Self {
338        self.raw_tx_forwarder = tx_forwarder;
339        self
340    }
341
342    /// Returns the gas cap.
343    pub const fn get_gas_cap(&self) -> &GasCap {
344        &self.gas_cap
345    }
346
347    /// Returns the maximum simulate blocks.
348    pub const fn get_max_simulate_blocks(&self) -> u64 {
349        self.max_simulate_blocks
350    }
351
352    /// Returns the ETH proof window.
353    pub const fn get_eth_proof_window(&self) -> u64 {
354        self.eth_proof_window
355    }
356
357    /// Returns a reference to the fee history cache config.
358    pub const fn get_fee_history_cache_config(&self) -> &FeeHistoryCacheConfig {
359        &self.fee_history_cache_config
360    }
361
362    /// Returns the proof permits.
363    pub const fn get_proof_permits(&self) -> usize {
364        self.proof_permits
365    }
366
367    /// Returns a reference to the ETH state cache config.
368    pub const fn get_eth_state_cache_config(&self) -> &EthStateCacheConfig {
369        &self.eth_state_cache_config
370    }
371
372    /// Returns a reference to the gas oracle config.
373    pub const fn get_gas_oracle_config(&self) -> &GasPriceOracleConfig {
374        &self.gas_oracle_config
375    }
376
377    /// Returns the max batch size.
378    pub const fn get_max_batch_size(&self) -> usize {
379        self.max_batch_size
380    }
381
382    /// Returns the pending block kind.
383    pub const fn get_pending_block_kind(&self) -> PendingBlockKind {
384        self.pending_block_kind
385    }
386
387    /// Returns a reference to the raw tx forwarder config.
388    pub const fn get_raw_tx_forwarder(&self) -> &ForwardConfig {
389        &self.raw_tx_forwarder
390    }
391
392    /// Returns a mutable reference to the fee history cache config.
393    pub const fn fee_history_cache_config_mut(&mut self) -> &mut FeeHistoryCacheConfig {
394        &mut self.fee_history_cache_config
395    }
396
397    /// Returns a mutable reference to the ETH state cache config.
398    pub const fn eth_state_cache_config_mut(&mut self) -> &mut EthStateCacheConfig {
399        &mut self.eth_state_cache_config
400    }
401
402    /// Returns a mutable reference to the gas oracle config.
403    pub const fn gas_oracle_config_mut(&mut self) -> &mut GasPriceOracleConfig {
404        &mut self.gas_oracle_config
405    }
406
407    /// Returns a mutable reference to the raw tx forwarder config.
408    pub const fn raw_tx_forwarder_mut(&mut self) -> &mut ForwardConfig {
409        &mut self.raw_tx_forwarder
410    }
411
412    /// Modifies the fee history cache configuration using a closure.
413    pub fn modify_fee_history_cache_config<F>(mut self, f: F) -> Self
414    where
415        F: FnOnce(&mut FeeHistoryCacheConfig),
416    {
417        f(&mut self.fee_history_cache_config);
418        self
419    }
420
421    /// Modifies the ETH state cache configuration using a closure.
422    pub fn modify_eth_state_cache_config<F>(mut self, f: F) -> Self
423    where
424        F: FnOnce(&mut EthStateCacheConfig),
425    {
426        f(&mut self.eth_state_cache_config);
427        self
428    }
429
430    /// Modifies the gas oracle configuration using a closure.
431    pub fn modify_gas_oracle_config<F>(mut self, f: F) -> Self
432    where
433        F: FnOnce(&mut GasPriceOracleConfig),
434    {
435        f(&mut self.gas_oracle_config);
436        self
437    }
438
439    /// Modifies the raw tx forwarder configuration using a closure.
440    pub fn modify_raw_tx_forwarder<F>(mut self, f: F) -> Self
441    where
442        F: FnOnce(&mut ForwardConfig),
443    {
444        f(&mut self.raw_tx_forwarder);
445        self
446    }
447
448    /// Builds the [`EthApiInner`] instance.
449    ///
450    /// If not configured, this will spawn the cache backend: [`EthStateCache::spawn`].
451    ///
452    /// # Panics
453    ///
454    /// This function panics if the blocking task pool cannot be built.
455    /// This will panic if called outside the context of a Tokio runtime.
456    pub fn build_inner(self) -> EthApiInner<N, Rpc>
457    where
458        Rpc: RpcConvert,
459        NextEnv: PendingEnvBuilder<N::Evm>,
460    {
461        let Self {
462            components,
463            rpc_converter,
464            eth_state_cache_config,
465            gas_oracle_config,
466            eth_cache,
467            gas_oracle,
468            gas_cap,
469            max_simulate_blocks,
470            eth_proof_window,
471            blocking_task_pool,
472            fee_history_cache_config,
473            proof_permits,
474            task_spawner,
475            next_env,
476            max_batch_size,
477            pending_block_kind,
478            raw_tx_forwarder,
479            send_raw_transaction_sync_timeout,
480        } = self;
481
482        let provider = components.provider().clone();
483
484        let eth_cache = eth_cache
485            .unwrap_or_else(|| EthStateCache::spawn(provider.clone(), eth_state_cache_config));
486        let gas_oracle = gas_oracle.unwrap_or_else(|| {
487            GasPriceOracle::new(provider.clone(), gas_oracle_config, eth_cache.clone())
488        });
489        let fee_history_cache =
490            FeeHistoryCache::<HeaderTy<N::Primitives>>::new(fee_history_cache_config);
491        let new_canonical_blocks = provider.canonical_state_stream();
492        let fhc = fee_history_cache.clone();
493        let cache = eth_cache.clone();
494        task_spawner.spawn_critical(
495            "cache canonical blocks for fee history task",
496            Box::pin(async move {
497                fee_history_cache_new_blocks_task(fhc, new_canonical_blocks, provider, cache).await;
498            }),
499        );
500
501        EthApiInner::new(
502            components,
503            eth_cache,
504            gas_oracle,
505            gas_cap,
506            max_simulate_blocks,
507            eth_proof_window,
508            blocking_task_pool.unwrap_or_else(|| {
509                BlockingTaskPool::build().expect("failed to build blocking task pool")
510            }),
511            fee_history_cache,
512            task_spawner,
513            proof_permits,
514            rpc_converter,
515            next_env,
516            max_batch_size,
517            pending_block_kind,
518            raw_tx_forwarder.forwarder_client(),
519            send_raw_transaction_sync_timeout,
520        )
521    }
522
523    /// Builds the [`EthApi`] instance.
524    ///
525    /// If not configured, this will spawn the cache backend: [`EthStateCache::spawn`].
526    ///
527    /// # Panics
528    ///
529    /// This function panics if the blocking task pool cannot be built.
530    /// This will panic if called outside the context of a Tokio runtime.
531    pub fn build(self) -> EthApi<N, Rpc>
532    where
533        Rpc: RpcConvert,
534        NextEnv: PendingEnvBuilder<N::Evm>,
535    {
536        EthApi { inner: Arc::new(self.build_inner()) }
537    }
538
539    /// Sets the timeout for `send_raw_transaction_sync` RPC method.
540    pub const fn send_raw_transaction_sync_timeout(mut self, timeout: Duration) -> Self {
541        self.send_raw_transaction_sync_timeout = timeout;
542        self
543    }
544}