1use crate::{
4 engine_ssz_proxy::{EngineSszApi, EngineSszProxyLayer},
5 engine_ssz_witness::EngineSszWitnessGenerator,
6 EthEngineTypes, EthEvmConfig,
7};
8use alloy_eips::{eip7840::BlobParams, merge::EPOCH_SLOTS};
9use alloy_network::Ethereum;
10use alloy_rpc_types_engine::ExecutionData;
11use reth_chainspec::{ChainSpec, EthChainSpec, EthereumHardforks, Hardforks};
12use reth_engine_local::LocalPayloadAttributesBuilder;
13use reth_engine_primitives::EngineTypes;
14use reth_ethereum_consensus::EthBeaconConsensus;
15use reth_ethereum_engine_primitives::{EthBuiltPayload, EthPayloadAttributes};
16use reth_ethereum_primitives::{EthPrimitives, TransactionSigned};
17use reth_evm::{ConfigureEvm, NextBlockEnvAttributes};
18#[cfg(not(feature = "jit"))]
19use reth_evm_ethereum::RethEvmFactory;
20#[cfg(feature = "jit")]
21use reth_evm_ethereum::{
22 JitBackend, JitMetrics, JitMode, RethEvmFactory, RuntimeConfig, RuntimeTuning,
23};
24use reth_network::{primitives::BasicNetworkPrimitives, NetworkHandle, PeersInfo};
25use reth_node_api::{
26 AddOnsContext, FullNodeComponents, HeaderTy, NodeAddOns, NodePrimitives,
27 PayloadAttributesBuilder, PrimitivesTy, TxTy,
28};
29use reth_node_builder::{
30 components::{
31 BasicPayloadServiceBuilder, ComponentsBuilder, ConsensusBuilder, ExecutorBuilder,
32 NetworkBuilder, PoolBuilder, TxPoolBuilder,
33 },
34 node::{FullNodeTypes, NodeTypes},
35 rpc::{
36 BasicEngineApiBuilder, BasicEngineValidatorBuilder, Either, EngineApiBuilder,
37 EngineValidatorAddOn, EngineValidatorBuilder, EthApiBuilder, EthApiCtx, EthApiFor,
38 EthRpcConverterFor, Identity, PayloadValidatorBuilder, RethAuthHttpMiddleware,
39 RethRpcAddOns, RethRpcMiddleware, RpcAddOns, RpcHandle, Stack,
40 },
41 BuilderContext, DebugNode, EngineApiExt, Node, NodeAdapter, PayloadBuilderConfig,
42};
43use reth_node_core::args::JitArgs;
44use reth_payload_primitives::PayloadTypes;
45use reth_provider::{providers::ProviderFactoryBuilder, EthStorage};
46use reth_rpc::{TestingApi, ValidationApi};
47use reth_rpc_api::servers::{BlockSubmissionValidationApiServer, TestingApiServer};
48use reth_rpc_builder::config::RethRpcServerConfig;
49use reth_rpc_eth_api::{
50 helpers::{
51 config::{EthConfigApiServer, EthConfigHandler},
52 pending_block::BuildPendingEnv,
53 },
54 RpcConvert, RpcTypes, SignableTxRequest,
55};
56use reth_rpc_eth_types::{error::FromEvmError, EthApiError};
57use reth_rpc_server_types::RethRpcModule;
58use reth_transaction_pool::{
59 blobstore::DiskFileBlobStore, EthTransactionPool, PoolPooledTx, PoolTransaction,
60 TransactionPool, TransactionValidationTaskExecutor,
61};
62use std::{marker::PhantomData, sync::Arc, time::SystemTime};
63#[cfg(feature = "jit")]
64use tracing::warn;
65use tracing::{debug, info};
66
67pub use crate::{payload::EthereumPayloadBuilder, EthereumEngineValidator};
68
69#[cfg(feature = "jit")]
71pub use reth_evm_ethereum::maybe_run_jit_helper;
72
73#[cfg(not(feature = "jit"))]
75pub const fn maybe_run_jit_helper() -> eyre::Result<std::ops::ControlFlow<()>> {
76 Ok(std::ops::ControlFlow::Continue(()))
77}
78
79#[derive(Debug, Default, Clone, Copy)]
81#[non_exhaustive]
82pub struct EthereumNode;
83
84impl EthereumNode {
85 pub fn components<Node>() -> ComponentsBuilder<
87 Node,
88 EthereumPoolBuilder,
89 BasicPayloadServiceBuilder<EthereumPayloadBuilder>,
90 EthereumNetworkBuilder,
91 EthereumExecutorBuilder,
92 EthereumConsensusBuilder,
93 >
94 where
95 Node: FullNodeTypes<
96 Types: NodeTypes<ChainSpec: Hardforks + EthereumHardforks, Primitives = EthPrimitives>,
97 >,
98 <Node::Types as NodeTypes>::Payload:
99 PayloadTypes<BuiltPayload = EthBuiltPayload, PayloadAttributes = EthPayloadAttributes>,
100 {
101 ComponentsBuilder::default()
102 .node_types::<Node>()
103 .pool(EthereumPoolBuilder::default())
104 .executor(EthereumExecutorBuilder::default())
105 .payload(BasicPayloadServiceBuilder::default())
106 .network(EthereumNetworkBuilder::default())
107 .consensus(EthereumConsensusBuilder::default())
108 }
109
110 pub fn provider_factory_builder() -> ProviderFactoryBuilder<Self> {
132 ProviderFactoryBuilder::default()
133 }
134}
135
136impl NodeTypes for EthereumNode {
137 type Primitives = EthPrimitives;
138 type ChainSpec = ChainSpec;
139 type Storage = EthStorage;
140 type Payload = EthEngineTypes;
141}
142
143#[derive(Debug)]
145pub struct EthereumEthApiBuilder<NetworkT = Ethereum>(PhantomData<NetworkT>);
146
147impl<NetworkT> Default for EthereumEthApiBuilder<NetworkT> {
148 fn default() -> Self {
149 Self(Default::default())
150 }
151}
152
153impl<N, NetworkT> EthApiBuilder<N> for EthereumEthApiBuilder<NetworkT>
154where
155 N: FullNodeComponents<
156 Types: NodeTypes<ChainSpec: Hardforks + EthereumHardforks>,
157 Evm: ConfigureEvm<NextBlockEnvCtx: BuildPendingEnv<HeaderTy<N::Types>>>,
158 >,
159 NetworkT: RpcTypes<TransactionRequest: SignableTxRequest<TxTy<N::Types>>>,
160 EthRpcConverterFor<N, NetworkT>: RpcConvert<
161 Primitives = PrimitivesTy<N::Types>,
162 Error = EthApiError,
163 Network = NetworkT,
164 Evm = N::Evm,
165 >,
166 EthApiError: FromEvmError<N::Evm>,
167{
168 type EthApi = EthApiFor<N, NetworkT>;
169
170 async fn build_eth_api(self, ctx: EthApiCtx<'_, N>) -> eyre::Result<Self::EthApi> {
171 Ok(ctx.eth_api_builder().map_converter(|r| r.with_network()).build())
172 }
173}
174
175#[derive(Debug)]
177pub struct EthereumAddOns<
178 N: FullNodeComponents,
179 EthB: EthApiBuilder<N>,
180 PVB,
181 EB = BasicEngineApiBuilder<PVB>,
182 EVB = BasicEngineValidatorBuilder<PVB>,
183 RpcMiddleware = Identity,
184 AuthHttpMiddleware = Identity,
185> {
186 inner: RpcAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>,
187}
188
189impl<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
190 EthereumAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
191where
192 N: FullNodeComponents,
193 EthB: EthApiBuilder<N>,
194{
195 pub const fn new(
197 inner: RpcAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>,
198 ) -> Self {
199 Self { inner }
200 }
201}
202
203impl<N> Default for EthereumAddOns<N, EthereumEthApiBuilder, EthereumEngineValidatorBuilder>
204where
205 N: FullNodeComponents<
206 Types: NodeTypes<
207 ChainSpec: EthereumHardforks + Clone + 'static,
208 Payload: EngineTypes<ExecutionData = ExecutionData>
209 + PayloadTypes<PayloadAttributes = EthPayloadAttributes>,
210 Primitives = EthPrimitives,
211 >,
212 >,
213 EthereumEthApiBuilder: EthApiBuilder<N>,
214{
215 fn default() -> Self {
216 Self::new(RpcAddOns::new(
217 EthereumEthApiBuilder::default(),
218 EthereumEngineValidatorBuilder::default(),
219 BasicEngineApiBuilder::default(),
220 BasicEngineValidatorBuilder::default(),
221 Default::default(),
222 Identity::new(),
223 ))
224 }
225}
226
227impl<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
228 EthereumAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
229where
230 N: FullNodeComponents,
231 EthB: EthApiBuilder<N>,
232{
233 pub fn with_engine_api<T>(
235 self,
236 engine_api_builder: T,
237 ) -> EthereumAddOns<N, EthB, PVB, T, EVB, RpcMiddleware, AuthHttpMiddleware>
238 where
239 T: Send,
240 {
241 let Self { inner } = self;
242 EthereumAddOns::new(inner.with_engine_api(engine_api_builder))
243 }
244
245 pub fn with_payload_validator<V, T>(
247 self,
248 payload_validator_builder: T,
249 ) -> EthereumAddOns<N, EthB, T, EB, EVB, RpcMiddleware, AuthHttpMiddleware> {
250 let Self { inner } = self;
251 EthereumAddOns::new(inner.with_payload_validator(payload_validator_builder))
252 }
253
254 pub fn with_rpc_middleware<T>(
256 self,
257 rpc_middleware: T,
258 ) -> EthereumAddOns<N, EthB, PVB, EB, EVB, T, AuthHttpMiddleware>
259 where
260 T: Send,
261 {
262 let Self { inner } = self;
263 EthereumAddOns::new(inner.with_rpc_middleware(rpc_middleware))
264 }
265
266 pub fn with_auth_http_middleware<T>(
268 self,
269 auth_http_middleware: T,
270 ) -> EthereumAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, T>
271 where
272 T: Send,
273 {
274 let Self { inner } = self;
275 EthereumAddOns::new(inner.with_auth_http_middleware(auth_http_middleware))
276 }
277
278 pub fn layer_auth_http_middleware<T>(
280 self,
281 layer: T,
282 ) -> EthereumAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, Stack<AuthHttpMiddleware, T>> {
283 let Self { inner } = self;
284 EthereumAddOns::new(inner.layer_auth_http_middleware(layer))
285 }
286
287 #[expect(clippy::type_complexity)]
289 pub fn option_layer_auth_http_middleware<T>(
290 self,
291 layer: Option<T>,
292 ) -> EthereumAddOns<
293 N,
294 EthB,
295 PVB,
296 EB,
297 EVB,
298 RpcMiddleware,
299 Stack<AuthHttpMiddleware, Either<T, Identity>>,
300 > {
301 let Self { inner } = self;
302 EthereumAddOns::new(inner.option_layer_auth_http_middleware(layer))
303 }
304
305 pub fn with_tokio_runtime(self, tokio_runtime: Option<tokio::runtime::Handle>) -> Self {
309 let Self { inner } = self;
310 Self { inner: inner.with_tokio_runtime(tokio_runtime) }
311 }
312}
313
314impl<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware> NodeAddOns<N>
315 for EthereumAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
316where
317 N: FullNodeComponents<
318 Types: NodeTypes<
319 ChainSpec: EthChainSpec + Hardforks + EthereumHardforks,
320 Primitives = EthPrimitives,
321 Payload: EngineTypes<ExecutionData = ExecutionData>,
322 >,
323 Evm: ConfigureEvm<NextBlockEnvCtx = NextBlockEnvAttributes>,
324 >,
325 EthB: EthApiBuilder<N>,
326 PVB: Send,
327 EB: EngineApiBuilder<N>,
328 EB::EngineApi: EngineSszApi,
329 EVB: EngineValidatorBuilder<N>,
330 EthApiError: FromEvmError<N::Evm>,
331 RpcMiddleware: RethRpcMiddleware,
332 AuthHttpMiddleware: RethAuthHttpMiddleware<Identity>,
333 Stack<EngineSszProxyLayer<EB::EngineApi>, AuthHttpMiddleware>: RethAuthHttpMiddleware<Identity>,
334{
335 type Handle = RpcHandle<N, EthB::EthApi>;
336
337 async fn launch_add_ons(
338 self,
339 ctx: reth_node_api::AddOnsContext<'_, N>,
340 ) -> eyre::Result<Self::Handle> {
341 let validation_api = ValidationApi::<_, _, <N::Types as NodeTypes>::Payload>::new(
342 ctx.node.provider().clone(),
343 Arc::new(ctx.node.consensus().clone()),
344 ctx.node.evm_config().clone(),
345 ctx.config.rpc.flashbots_config(),
346 ctx.node.task_executor().clone(),
347 Arc::new(EthereumEngineValidator::new(ctx.config.chain.clone())),
348 ctx.sender_recovery_cache.clone(),
349 );
350
351 let eth_config =
352 EthConfigHandler::new(ctx.node.provider().clone(), ctx.node.evm_config().clone());
353
354 let testing_skip_invalid_transactions = ctx.config.rpc.testing_skip_invalid_transactions;
355 let testing_gas_limit_override = ctx.config.rpc.testing_gas_limit;
356 let testing_desired_gas_limit = ctx.config.builder.gas_limit_for(ctx.config.chain.chain());
357 let testing_engine_handle = ctx.beacon_engine_handle.clone();
358
359 let (ssz_proxy_layer, ssz_proxy_handle) = EngineSszProxyLayer::new();
360 ssz_proxy_handle.set_witness_handler_sync(Arc::new(EngineSszWitnessGenerator::new(
361 ctx.node.provider().clone(),
362 ctx.node.evm_config().clone(),
363 ctx.node.task_executor().clone(),
364 )));
365
366 self.inner
367 .map_engine_api(|engine_api_builder| {
368 EngineApiExt::new(engine_api_builder, move |engine_api| {
369 ssz_proxy_handle.set_engine_api_sync(engine_api);
370 })
371 })
372 .map_auth_http_middleware(|middleware| Stack::new(ssz_proxy_layer, middleware))
373 .launch_add_ons_with(ctx, move |container| {
374 container.modules.merge_if_module_configured(
375 RethRpcModule::Flashbots,
376 validation_api.into_rpc(),
377 )?;
378
379 container
380 .modules
381 .merge_if_module_configured(RethRpcModule::Eth, eth_config.into_rpc())?;
382
383 let mut testing_api = TestingApi::new(
386 container.registry.eth_api().clone(),
387 container.registry.evm_config().clone(),
388 testing_desired_gas_limit,
389 testing_engine_handle,
390 );
391 if testing_skip_invalid_transactions {
392 testing_api = testing_api.with_skip_invalid_transactions();
393 }
394 if let Some(gas_limit) = testing_gas_limit_override {
395 testing_api = testing_api.with_gas_limit_override(gas_limit);
396 }
397 container
398 .modules
399 .merge_if_module_configured(RethRpcModule::Testing, testing_api.into_rpc())?;
400
401 Ok(())
402 })
403 .await
404 }
405}
406
407impl<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware> RethRpcAddOns<N>
408 for EthereumAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
409where
410 N: FullNodeComponents<
411 Types: NodeTypes<
412 ChainSpec: Hardforks + EthereumHardforks,
413 Primitives = EthPrimitives,
414 Payload: EngineTypes<ExecutionData = ExecutionData>,
415 >,
416 Evm: ConfigureEvm<NextBlockEnvCtx = NextBlockEnvAttributes>,
417 >,
418 EthB: EthApiBuilder<N>,
419 PVB: PayloadValidatorBuilder<N>,
420 EB: EngineApiBuilder<N>,
421 EB::EngineApi: EngineSszApi,
422 EVB: EngineValidatorBuilder<N>,
423 EthApiError: FromEvmError<N::Evm>,
424 RpcMiddleware: RethRpcMiddleware,
425 AuthHttpMiddleware: RethAuthHttpMiddleware<Identity>,
426 Stack<EngineSszProxyLayer<EB::EngineApi>, AuthHttpMiddleware>: RethAuthHttpMiddleware<Identity>,
427{
428 type EthApi = EthB::EthApi;
429
430 fn hooks_mut(&mut self) -> &mut reth_node_builder::rpc::RpcHooks<N, Self::EthApi> {
431 self.inner.hooks_mut()
432 }
433}
434
435impl<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware> EngineValidatorAddOn<N>
436 for EthereumAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
437where
438 N: FullNodeComponents<
439 Types: NodeTypes<
440 ChainSpec: EthChainSpec + EthereumHardforks,
441 Primitives = EthPrimitives,
442 Payload: EngineTypes<ExecutionData = ExecutionData>,
443 >,
444 Evm: ConfigureEvm<NextBlockEnvCtx = NextBlockEnvAttributes>,
445 >,
446 EthB: EthApiBuilder<N>,
447 PVB: Send,
448 EB: EngineApiBuilder<N>,
449 EVB: EngineValidatorBuilder<N>,
450 EthApiError: FromEvmError<N::Evm>,
451 RpcMiddleware: Send,
452 AuthHttpMiddleware: Send,
453{
454 type ValidatorBuilder = EVB;
455
456 fn engine_validator_builder(&self) -> Self::ValidatorBuilder {
457 self.inner.engine_validator_builder()
458 }
459}
460
461impl<N> Node<N> for EthereumNode
462where
463 N: FullNodeTypes<Types = Self>,
464{
465 type ComponentsBuilder = ComponentsBuilder<
466 N,
467 EthereumPoolBuilder,
468 BasicPayloadServiceBuilder<EthereumPayloadBuilder>,
469 EthereumNetworkBuilder,
470 EthereumExecutorBuilder,
471 EthereumConsensusBuilder,
472 >;
473
474 type AddOns =
475 EthereumAddOns<NodeAdapter<N>, EthereumEthApiBuilder, EthereumEngineValidatorBuilder>;
476
477 fn components_builder(&self) -> Self::ComponentsBuilder {
478 Self::components()
479 }
480
481 fn add_ons(&self) -> Self::AddOns {
482 EthereumAddOns::default()
483 }
484}
485
486impl<N: FullNodeComponents<Types = Self>> DebugNode<N> for EthereumNode {
487 type RpcBlock = alloy_rpc_types_eth::Block;
488
489 fn rpc_to_primitive_block(rpc_block: Self::RpcBlock) -> reth_ethereum_primitives::Block {
490 rpc_block.into_consensus().convert_transactions()
491 }
492
493 fn local_payload_attributes_builder(
494 chain_spec: &Self::ChainSpec,
495 ) -> impl PayloadAttributesBuilder<<Self::Payload as PayloadTypes>::PayloadAttributes> {
496 LocalPayloadAttributesBuilder::new(Arc::new(chain_spec.clone()))
497 }
498}
499
500#[cfg(feature = "jit")]
502fn jit_runtime_config(jit: &JitArgs) -> RuntimeConfig {
503 let default_tuning = RuntimeTuning::default();
504 let tuning = RuntimeTuning {
505 channel_capacity: jit.channel_capacity,
506 jit_hot_threshold: jit.hot_threshold,
507 jit_max_bytecode_len: jit.max_bytecode_len,
508 jit_max_pending_jobs: jit.max_pending_jobs,
509 jit_worker_count: jit.worker_count.unwrap_or(default_tuning.jit_worker_count),
510 resident_code_cache_bytes: jit.code_cache_bytes,
511 idle_evict_duration: Some(jit.idle_evict_duration),
512 ..default_tuning
513 };
514
515 RuntimeConfig {
516 enabled: jit.enabled,
517 tuning,
518 debug_assertions: jit.debug,
519 blocking: jit.blocking,
520 jit_mode: JitMode::OutOfProcess,
521 ..RuntimeConfig::default()
522 }
523}
524
525#[cfg(feature = "jit")]
531#[allow(clippy::type_complexity)]
532pub fn build_evm_config<C: EthereumHardforks>(
533 chain_spec: Arc<C>,
534 jit: &JitArgs,
535 dump_dir: Option<std::path::PathBuf>,
536) -> eyre::Result<(EthEvmConfig<C, RethEvmFactory>, Option<Arc<JitMetrics>>)> {
537 if !jit.enabled {
538 let config = RuntimeConfig { blocking: false, ..jit_runtime_config(jit) };
541 #[cfg(not(unix))]
542 let config = RuntimeConfig { jit_mode: JitMode::InProcess, ..config };
543 let factory = RethEvmFactory::new(JitBackend::new(config)?);
544 return Ok((EthEvmConfig::new_with_evm_factory(chain_spec, factory), None));
545 }
546
547 let mut config = jit_runtime_config(jit);
548 config.dump_dir = dump_dir;
549
550 let jit_metrics = Arc::new(JitMetrics::default());
551 let compilation_metrics = jit_metrics.clone();
552 config.on_compilation = Some(Arc::new(move |event| {
553 compilation_metrics.record_compilation(&event);
554 }));
555
556 let tuning = config.tuning;
557 let jit_mode = config.jit_mode;
558 let backend = JitBackend::new(config)?;
559
560 warn!(target: "reth::cli",
561 hot_threshold = tuning.jit_hot_threshold,
562 workers = tuning.jit_worker_count,
563 mode = ?jit_mode,
564 blocking = jit.blocking,
565 "Started experimental evm2 JIT backend; this may cause instability",
566 );
567
568 let factory = RethEvmFactory::new_with_metrics(backend, jit_metrics.as_ref().clone());
569 let evm_config = EthEvmConfig::new_with_evm_factory(chain_spec, factory);
570
571 Ok((evm_config, Some(jit_metrics)))
572}
573
574#[cfg(not(feature = "jit"))]
579#[allow(clippy::type_complexity)]
580pub fn build_evm_config<C: EthereumHardforks>(
581 chain_spec: Arc<C>,
582 jit: &JitArgs,
583 _dump_dir: Option<std::path::PathBuf>,
584) -> eyre::Result<(EthEvmConfig<C, RethEvmFactory>, Option<()>)> {
585 if jit.enabled {
586 eyre::bail!(
587 "JIT compilation was requested but this binary was compiled without the `jit` feature"
588 );
589 }
590 let factory = RethEvmFactory::disabled();
591 Ok((EthEvmConfig::new_with_evm_factory(chain_spec, factory), None))
592}
593
594#[derive(Debug, Default, Clone, Copy)]
596#[non_exhaustive]
597pub struct EthereumExecutorBuilder;
598
599impl<Types, Node> ExecutorBuilder<Node> for EthereumExecutorBuilder
600where
601 Types: NodeTypes<ChainSpec: Hardforks + EthereumHardforks, Primitives = EthPrimitives>,
602 Node: FullNodeTypes<Types = Types>,
603{
604 type EVM = EthEvmConfig<Types::ChainSpec, RethEvmFactory>;
605
606 async fn build_evm(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::EVM> {
607 let jit = &ctx.config().jit;
608 let dump_dir = jit.debug.then(|| ctx.config().datadir().data_dir().join("jit"));
609
610 let (mut evm_config, jit_metrics) = build_evm_config(ctx.chain_spec(), jit, dump_dir)?;
611 if let Some(cache) = ctx.sender_recovery_cache() {
612 evm_config = evm_config.with_sender_recovery_cache(cache.clone());
613 }
614
615 #[cfg(not(feature = "jit"))]
616 let _ = jit_metrics;
617
618 #[cfg(feature = "jit")]
619 if let Some(jit_metrics) = jit_metrics {
620 let metrics_backend = evm_config.executor_factory.evm_factory().backend().clone();
621 ctx.task_executor().spawn_with_graceful_shutdown_signal(|shutdown| async move {
622 let mut shutdown = std::pin::pin!(shutdown);
623 loop {
624 tokio::select! {
625 _ = tokio::time::sleep(std::time::Duration::from_secs(5)) => {
626 jit_metrics.record(&metrics_backend.stats());
627 }
628 _ = &mut shutdown => break,
629 }
630 }
631 });
632 }
633
634 Ok(evm_config)
635 }
636}
637
638#[derive(Debug, Clone, Copy)]
643#[non_exhaustive]
644pub struct EthereumPoolBuilder {
645 init_kzg_settings: bool,
646}
647
648impl EthereumPoolBuilder {
649 pub const fn new() -> Self {
651 Self { init_kzg_settings: false }
652 }
653
654 pub const fn with_init_kzg_settings(mut self, init_kzg_settings: bool) -> Self {
656 self.init_kzg_settings = init_kzg_settings;
657 self
658 }
659}
660
661impl Default for EthereumPoolBuilder {
662 fn default() -> Self {
663 Self::new()
664 }
665}
666
667impl<Types, Node, Evm> PoolBuilder<Node, Evm> for EthereumPoolBuilder
668where
669 Types: NodeTypes<
670 ChainSpec: EthereumHardforks,
671 Primitives: NodePrimitives<SignedTx = TransactionSigned>,
672 >,
673 Node: FullNodeTypes<Types = Types>,
674 Evm: ConfigureEvm<Primitives = PrimitivesTy<Types>> + 'static,
675{
676 type Pool = EthTransactionPool<Node::Provider, DiskFileBlobStore, Evm>;
677
678 async fn build_pool(
679 self,
680 ctx: &BuilderContext<Node>,
681 evm_config: Evm,
682 ) -> eyre::Result<Self::Pool> {
683 let pool_config = ctx.pool_config();
684
685 let blobs_disabled = ctx.config().txpool.disable_blobs_support ||
686 ctx.config().txpool.blobpool_max_count == 0;
687
688 let blob_cache_size = if let Some(blob_cache_size) = pool_config.blob_cache_size {
689 Some(blob_cache_size)
690 } else {
691 let current_timestamp =
694 SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_secs();
695 let blob_params = ctx
696 .chain_spec()
697 .blob_params_at_timestamp(current_timestamp)
698 .unwrap_or_else(BlobParams::cancun);
699
700 Some((blob_params.target_blob_count * EPOCH_SLOTS * 2) as u32)
703 };
704
705 let blob_store =
706 reth_node_builder::components::create_blob_store_with_cache(ctx, blob_cache_size)?;
707
708 let validator =
709 TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone(), evm_config)
710 .set_eip4844(!blobs_disabled)
711 .kzg_settings(ctx.kzg_settings()?)
712 .with_max_tx_input_bytes(ctx.config().txpool.max_tx_input_bytes)
713 .with_local_transactions_config(pool_config.local_transactions_config.clone())
714 .set_tx_fee_cap(ctx.config().rpc.rpc_tx_fee_cap)
715 .with_max_tx_gas_limit(ctx.config().txpool.max_tx_gas_limit)
716 .with_minimum_priority_fee(ctx.config().txpool.minimum_priority_fee)
717 .with_additional_tasks(ctx.config().txpool.additional_validation_tasks)
718 .build_with_tasks(ctx.task_executor().clone(), blob_store.clone());
719
720 if (validator.validator().eip4844() || self.init_kzg_settings) &&
721 !ctx.config().debug.lazy_kzg_settings
722 {
723 let kzg_settings = validator.validator().kzg_settings().clone();
727 ctx.task_executor().spawn_blocking_task(async move {
728 let _ = kzg_settings.get();
729 debug!(target: "reth::cli", "Initialized KZG settings");
730 });
731 }
732
733 let transaction_pool = TxPoolBuilder::new(ctx)
734 .with_validator(validator)
735 .build_and_spawn_maintenance_task(blob_store, pool_config)?;
736
737 info!(target: "reth::cli", "Transaction pool initialized");
738 debug!(target: "reth::cli", "Spawned txpool maintenance task");
739
740 Ok(transaction_pool)
741 }
742}
743
744#[derive(Debug, Default, Clone, Copy)]
746pub struct EthereumNetworkBuilder {
747 }
749
750impl<Node, Pool> NetworkBuilder<Node, Pool> for EthereumNetworkBuilder
751where
752 Node: FullNodeTypes<Types: NodeTypes<ChainSpec: Hardforks>>,
753 Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
754 + Unpin
755 + 'static,
756{
757 type Network =
758 NetworkHandle<BasicNetworkPrimitives<PrimitivesTy<Node::Types>, PoolPooledTx<Pool>>>;
759
760 async fn build_network(
761 self,
762 ctx: &BuilderContext<Node>,
763 pool: Pool,
764 ) -> eyre::Result<Self::Network> {
765 let network = ctx.network_builder().await?;
766 let handle = ctx.start_network(network, pool);
767 info!(target: "reth::cli", enode=%handle.local_node_record(), "P2P networking initialized");
768 Ok(handle)
769 }
770}
771
772#[derive(Debug, Default, Clone, Copy)]
774pub struct EthereumConsensusBuilder {
775 }
777
778impl<Node> ConsensusBuilder<Node> for EthereumConsensusBuilder
779where
780 Node: FullNodeTypes<
781 Types: NodeTypes<ChainSpec: EthChainSpec + EthereumHardforks, Primitives = EthPrimitives>,
782 >,
783{
784 type Consensus = Arc<EthBeaconConsensus<<Node::Types as NodeTypes>::ChainSpec>>;
785
786 async fn build_consensus(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Consensus> {
787 Ok(Arc::new(EthBeaconConsensus::new(ctx.chain_spec())))
788 }
789}
790
791#[derive(Debug, Default, Clone)]
793#[non_exhaustive]
794pub struct EthereumEngineValidatorBuilder;
795
796impl<Node, Types> PayloadValidatorBuilder<Node> for EthereumEngineValidatorBuilder
797where
798 Types: NodeTypes<
799 ChainSpec: Hardforks + EthereumHardforks + 'static,
800 Payload: EngineTypes<ExecutionData = ExecutionData>
801 + PayloadTypes<PayloadAttributes = EthPayloadAttributes>,
802 Primitives = EthPrimitives,
803 >,
804 Node: FullNodeComponents<Types = Types>,
805{
806 type Validator = EthereumEngineValidator<Types::ChainSpec>;
807
808 async fn build(self, ctx: &AddOnsContext<'_, Node>) -> eyre::Result<Self::Validator> {
809 Ok(EthereumEngineValidator::new(ctx.config.chain.clone()))
810 }
811}