1use crate::{BeaconConsensusEngineEvent, BeaconConsensusEngineHandle};
4use alloy_rpc_types::engine::ClientVersionV1;
5use alloy_rpc_types_engine::ExecutionData;
6use futures::TryFutureExt;
7use jsonrpsee::RpcModule;
8use reth_chain_state::CanonStateSubscriptions;
9use reth_chainspec::{ChainSpecProvider, EthereumHardforks};
10use reth_node_api::{
11 AddOnsContext, BlockTy, EngineTypes, EngineValidator, FullNodeComponents, FullNodeTypes,
12 NodeAddOns, NodeTypes, PayloadTypes, ReceiptTy,
13};
14use reth_node_core::{
15 node_config::NodeConfig,
16 version::{CARGO_PKG_VERSION, CLIENT_CODE, NAME_CLIENT, VERGEN_GIT_SHA},
17};
18use reth_payload_builder::{PayloadBuilderHandle, PayloadStore};
19use reth_rpc::eth::{EthApiTypes, FullEthApiServer};
20use reth_rpc_api::{eth::helpers::AddDevSigners, IntoEngineApiRpcModule};
21use reth_rpc_builder::{
22 auth::{AuthRpcModule, AuthServerHandle},
23 config::RethRpcServerConfig,
24 RpcModuleBuilder, RpcRegistryInner, RpcServerHandle, TransportRpcModules,
25};
26use reth_rpc_engine_api::{capabilities::EngineCapabilities, EngineApi};
27use reth_rpc_eth_types::{cache::cache_new_blocks_task, EthConfig, EthStateCache};
28use reth_tokio_util::EventSender;
29use reth_tracing::tracing::{debug, info};
30use std::{
31 fmt::{self, Debug},
32 future::Future,
33 ops::{Deref, DerefMut},
34};
35
36#[derive(Debug, Clone)]
40pub struct RethRpcServerHandles {
41 pub rpc: RpcServerHandle,
43 pub auth: AuthServerHandle,
45}
46
47pub struct RpcHooks<Node: FullNodeComponents, EthApi> {
49 pub on_rpc_started: Box<dyn OnRpcStarted<Node, EthApi>>,
51 pub extend_rpc_modules: Box<dyn ExtendRpcModules<Node, EthApi>>,
53}
54
55impl<Node, EthApi> Default for RpcHooks<Node, EthApi>
56where
57 Node: FullNodeComponents,
58 EthApi: EthApiTypes,
59{
60 fn default() -> Self {
61 Self { on_rpc_started: Box::<()>::default(), extend_rpc_modules: Box::<()>::default() }
62 }
63}
64
65impl<Node, EthApi> RpcHooks<Node, EthApi>
66where
67 Node: FullNodeComponents,
68 EthApi: EthApiTypes,
69{
70 pub(crate) fn set_on_rpc_started<F>(&mut self, hook: F) -> &mut Self
72 where
73 F: OnRpcStarted<Node, EthApi> + 'static,
74 {
75 self.on_rpc_started = Box::new(hook);
76 self
77 }
78
79 #[expect(unused)]
81 pub(crate) fn on_rpc_started<F>(mut self, hook: F) -> Self
82 where
83 F: OnRpcStarted<Node, EthApi> + 'static,
84 {
85 self.set_on_rpc_started(hook);
86 self
87 }
88
89 pub(crate) fn set_extend_rpc_modules<F>(&mut self, hook: F) -> &mut Self
91 where
92 F: ExtendRpcModules<Node, EthApi> + 'static,
93 {
94 self.extend_rpc_modules = Box::new(hook);
95 self
96 }
97
98 #[expect(unused)]
100 pub(crate) fn extend_rpc_modules<F>(mut self, hook: F) -> Self
101 where
102 F: ExtendRpcModules<Node, EthApi> + 'static,
103 {
104 self.set_extend_rpc_modules(hook);
105 self
106 }
107}
108
109impl<Node, EthApi> fmt::Debug for RpcHooks<Node, EthApi>
110where
111 Node: FullNodeComponents,
112 EthApi: EthApiTypes,
113{
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 f.debug_struct("RpcHooks")
116 .field("on_rpc_started", &"...")
117 .field("extend_rpc_modules", &"...")
118 .finish()
119 }
120}
121
122pub trait OnRpcStarted<Node: FullNodeComponents, EthApi: EthApiTypes>: Send {
124 fn on_rpc_started(
126 self: Box<Self>,
127 ctx: RpcContext<'_, Node, EthApi>,
128 handles: RethRpcServerHandles,
129 ) -> eyre::Result<()>;
130}
131
132impl<Node, EthApi, F> OnRpcStarted<Node, EthApi> for F
133where
134 F: FnOnce(RpcContext<'_, Node, EthApi>, RethRpcServerHandles) -> eyre::Result<()> + Send,
135 Node: FullNodeComponents,
136 EthApi: EthApiTypes,
137{
138 fn on_rpc_started(
139 self: Box<Self>,
140 ctx: RpcContext<'_, Node, EthApi>,
141 handles: RethRpcServerHandles,
142 ) -> eyre::Result<()> {
143 (*self)(ctx, handles)
144 }
145}
146
147impl<Node, EthApi> OnRpcStarted<Node, EthApi> for ()
148where
149 Node: FullNodeComponents,
150 EthApi: EthApiTypes,
151{
152 fn on_rpc_started(
153 self: Box<Self>,
154 _: RpcContext<'_, Node, EthApi>,
155 _: RethRpcServerHandles,
156 ) -> eyre::Result<()> {
157 Ok(())
158 }
159}
160
161pub trait ExtendRpcModules<Node: FullNodeComponents, EthApi: EthApiTypes>: Send {
163 fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()>;
165}
166
167impl<Node, EthApi, F> ExtendRpcModules<Node, EthApi> for F
168where
169 F: FnOnce(RpcContext<'_, Node, EthApi>) -> eyre::Result<()> + Send,
170 Node: FullNodeComponents,
171 EthApi: EthApiTypes,
172{
173 fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> {
174 (*self)(ctx)
175 }
176}
177
178impl<Node, EthApi> ExtendRpcModules<Node, EthApi> for ()
179where
180 Node: FullNodeComponents,
181 EthApi: EthApiTypes,
182{
183 fn extend_rpc_modules(self: Box<Self>, _: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> {
184 Ok(())
185 }
186}
187
188#[derive(Debug, Clone)]
190#[expect(clippy::type_complexity)]
191pub struct RpcRegistry<Node: FullNodeComponents, EthApi: EthApiTypes> {
192 pub(crate) registry: RpcRegistryInner<
193 Node::Provider,
194 Node::Pool,
195 Node::Network,
196 EthApi,
197 Node::Evm,
198 Node::Consensus,
199 >,
200}
201
202impl<Node, EthApi> Deref for RpcRegistry<Node, EthApi>
203where
204 Node: FullNodeComponents,
205 EthApi: EthApiTypes,
206{
207 type Target = RpcRegistryInner<
208 Node::Provider,
209 Node::Pool,
210 Node::Network,
211 EthApi,
212 Node::Evm,
213 Node::Consensus,
214 >;
215
216 fn deref(&self) -> &Self::Target {
217 &self.registry
218 }
219}
220
221impl<Node, EthApi> DerefMut for RpcRegistry<Node, EthApi>
222where
223 Node: FullNodeComponents,
224 EthApi: EthApiTypes,
225{
226 fn deref_mut(&mut self) -> &mut Self::Target {
227 &mut self.registry
228 }
229}
230
231#[expect(missing_debug_implementations)]
239pub struct RpcContext<'a, Node: FullNodeComponents, EthApi: EthApiTypes> {
240 pub(crate) node: Node,
242
243 pub(crate) config: &'a NodeConfig<<Node::Types as NodeTypes>::ChainSpec>,
245
246 pub registry: &'a mut RpcRegistry<Node, EthApi>,
250 pub modules: &'a mut TransportRpcModules,
255 pub auth_module: &'a mut AuthRpcModule,
259}
260
261impl<Node, EthApi> RpcContext<'_, Node, EthApi>
262where
263 Node: FullNodeComponents,
264 EthApi: EthApiTypes,
265{
266 pub const fn config(&self) -> &NodeConfig<<Node::Types as NodeTypes>::ChainSpec> {
268 self.config
269 }
270
271 pub const fn node(&self) -> &Node {
273 &self.node
274 }
275
276 pub fn pool(&self) -> &Node::Pool {
278 self.node.pool()
279 }
280
281 pub fn provider(&self) -> &Node::Provider {
283 self.node.provider()
284 }
285
286 pub fn network(&self) -> &Node::Network {
288 self.node.network()
289 }
290
291 pub fn payload_builder_handle(
293 &self,
294 ) -> &PayloadBuilderHandle<<Node::Types as NodeTypes>::Payload> {
295 self.node.payload_builder_handle()
296 }
297}
298
299pub struct RpcHandle<Node: FullNodeComponents, EthApi: EthApiTypes> {
301 pub rpc_server_handles: RethRpcServerHandles,
303 pub rpc_registry: RpcRegistry<Node, EthApi>,
305 pub engine_events:
310 EventSender<BeaconConsensusEngineEvent<<Node::Types as NodeTypes>::Primitives>>,
311 pub beacon_engine_handle: BeaconConsensusEngineHandle<<Node::Types as NodeTypes>::Payload>,
313}
314
315impl<Node: FullNodeComponents, EthApi: EthApiTypes> Clone for RpcHandle<Node, EthApi> {
316 fn clone(&self) -> Self {
317 Self {
318 rpc_server_handles: self.rpc_server_handles.clone(),
319 rpc_registry: self.rpc_registry.clone(),
320 engine_events: self.engine_events.clone(),
321 beacon_engine_handle: self.beacon_engine_handle.clone(),
322 }
323 }
324}
325
326impl<Node: FullNodeComponents, EthApi: EthApiTypes> Deref for RpcHandle<Node, EthApi> {
327 type Target = RpcRegistry<Node, EthApi>;
328
329 fn deref(&self) -> &Self::Target {
330 &self.rpc_registry
331 }
332}
333
334impl<Node: FullNodeComponents, EthApi: EthApiTypes> Debug for RpcHandle<Node, EthApi>
335where
336 RpcRegistry<Node, EthApi>: Debug,
337{
338 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
339 f.debug_struct("RpcHandle")
340 .field("rpc_server_handles", &self.rpc_server_handles)
341 .field("rpc_registry", &self.rpc_registry)
342 .finish()
343 }
344}
345
346pub struct RpcAddOns<
357 Node: FullNodeComponents,
358 EthB: EthApiBuilder<Node>,
359 EV,
360 EB = BasicEngineApiBuilder<EV>,
361> {
362 pub hooks: RpcHooks<Node, EthB::EthApi>,
364 eth_api_builder: EthB,
366 engine_validator_builder: EV,
368 engine_api_builder: EB,
370}
371
372impl<Node, EthB, EV, EB> Debug for RpcAddOns<Node, EthB, EV, EB>
373where
374 Node: FullNodeComponents,
375 EthB: EthApiBuilder<Node>,
376 EV: Debug,
377 EB: Debug,
378{
379 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380 f.debug_struct("RpcAddOns")
381 .field("hooks", &self.hooks)
382 .field("eth_api_builder", &"...")
383 .field("engine_validator_builder", &self.engine_validator_builder)
384 .field("engine_api_builder", &self.engine_api_builder)
385 .finish()
386 }
387}
388
389impl<Node, EthB, EV, EB> RpcAddOns<Node, EthB, EV, EB>
390where
391 Node: FullNodeComponents,
392 EthB: EthApiBuilder<Node>,
393{
394 pub fn new(
396 eth_api_builder: EthB,
397 engine_validator_builder: EV,
398 engine_api_builder: EB,
399 ) -> Self {
400 Self {
401 hooks: RpcHooks::default(),
402 eth_api_builder,
403 engine_validator_builder,
404 engine_api_builder,
405 }
406 }
407
408 pub fn with_engine_api<T>(self, engine_api_builder: T) -> RpcAddOns<Node, EthB, EV, T> {
410 let Self { hooks, eth_api_builder, engine_validator_builder, .. } = self;
411 RpcAddOns { hooks, eth_api_builder, engine_validator_builder, engine_api_builder }
412 }
413
414 pub fn with_engine_validator<T>(
416 self,
417 engine_validator_builder: T,
418 ) -> RpcAddOns<Node, EthB, T, EB> {
419 let Self { hooks, eth_api_builder, engine_api_builder, .. } = self;
420 RpcAddOns { hooks, eth_api_builder, engine_validator_builder, engine_api_builder }
421 }
422
423 pub fn on_rpc_started<F>(mut self, hook: F) -> Self
425 where
426 F: FnOnce(RpcContext<'_, Node, EthB::EthApi>, RethRpcServerHandles) -> eyre::Result<()>
427 + Send
428 + 'static,
429 {
430 self.hooks.set_on_rpc_started(hook);
431 self
432 }
433
434 pub fn extend_rpc_modules<F>(mut self, hook: F) -> Self
436 where
437 F: FnOnce(RpcContext<'_, Node, EthB::EthApi>) -> eyre::Result<()> + Send + 'static,
438 {
439 self.hooks.set_extend_rpc_modules(hook);
440 self
441 }
442}
443
444impl<Node, EthB, EV, EB> Default for RpcAddOns<Node, EthB, EV, EB>
445where
446 Node: FullNodeComponents,
447 EthB: EthApiBuilder<Node>,
448 EV: Default,
449 EB: Default,
450{
451 fn default() -> Self {
452 Self::new(EthB::default(), EV::default(), EB::default())
453 }
454}
455
456impl<N, EthB, EV, EB> RpcAddOns<N, EthB, EV, EB>
457where
458 N: FullNodeComponents,
459 N::Provider: ChainSpecProvider<ChainSpec: EthereumHardforks>,
460 EthB: EthApiBuilder<N>,
461 EV: EngineValidatorBuilder<N>,
462 EB: EngineApiBuilder<N>,
463{
464 pub async fn launch_add_ons_with<F>(
467 self,
468 ctx: AddOnsContext<'_, N>,
469 ext: F,
470 ) -> eyre::Result<RpcHandle<N, EthB::EthApi>>
471 where
472 F: FnOnce(
473 &mut TransportRpcModules,
474 &mut AuthRpcModule,
475 &mut RpcRegistry<N, EthB::EthApi>,
476 ) -> eyre::Result<()>,
477 {
478 let Self { eth_api_builder, engine_api_builder, hooks, .. } = self;
479
480 let engine_api = engine_api_builder.build_engine_api(&ctx).await?;
481 let AddOnsContext { node, config, beacon_engine_handle, jwt_secret, engine_events } = ctx;
482
483 info!(target: "reth::cli", "Engine API handler initialized");
484
485 let cache = EthStateCache::spawn_with(
486 node.provider().clone(),
487 config.rpc.eth_config().cache,
488 node.task_executor().clone(),
489 );
490
491 let new_canonical_blocks = node.provider().canonical_state_stream();
492 let c = cache.clone();
493 node.task_executor().spawn_critical(
494 "cache canonical blocks task",
495 Box::pin(async move {
496 cache_new_blocks_task(c, new_canonical_blocks).await;
497 }),
498 );
499
500 let ctx = EthApiCtx { components: &node, config: config.rpc.eth_config(), cache };
501 let eth_api = eth_api_builder.build_eth_api(ctx).await?;
502
503 let auth_config = config.rpc.auth_server_config(jwt_secret)?;
504 let module_config = config.rpc.transport_rpc_module_config();
505 debug!(target: "reth::cli", http=?module_config.http(), ws=?module_config.ws(), "Using RPC module config");
506
507 let (mut modules, mut auth_module, registry) = RpcModuleBuilder::default()
508 .with_provider(node.provider().clone())
509 .with_pool(node.pool().clone())
510 .with_network(node.network().clone())
511 .with_executor(Box::new(node.task_executor().clone()))
512 .with_evm_config(node.evm_config().clone())
513 .with_consensus(node.consensus().clone())
514 .build_with_auth_server(module_config, engine_api, eth_api);
515
516 if config.dev.dev {
518 registry.eth_api().with_dev_accounts();
519 }
520
521 let mut registry = RpcRegistry { registry };
522 let ctx = RpcContext {
523 node: node.clone(),
524 config,
525 registry: &mut registry,
526 modules: &mut modules,
527 auth_module: &mut auth_module,
528 };
529
530 let RpcHooks { on_rpc_started, extend_rpc_modules } = hooks;
531
532 ext(ctx.modules, ctx.auth_module, ctx.registry)?;
533 extend_rpc_modules.extend_rpc_modules(ctx)?;
534
535 let server_config = config.rpc.rpc_server_config();
536 let cloned_modules = modules.clone();
537 let launch_rpc = server_config.start(&cloned_modules).map_ok(|handle| {
538 if let Some(path) = handle.ipc_endpoint() {
539 info!(target: "reth::cli", %path, "RPC IPC server started");
540 }
541 if let Some(addr) = handle.http_local_addr() {
542 info!(target: "reth::cli", url=%addr, "RPC HTTP server started");
543 }
544 if let Some(addr) = handle.ws_local_addr() {
545 info!(target: "reth::cli", url=%addr, "RPC WS server started");
546 }
547 handle
548 });
549
550 let launch_auth = auth_module.clone().start_server(auth_config).map_ok(|handle| {
551 let addr = handle.local_addr();
552 if let Some(ipc_endpoint) = handle.ipc_endpoint() {
553 info!(target: "reth::cli", url=%addr, ipc_endpoint=%ipc_endpoint, "RPC auth server started");
554 } else {
555 info!(target: "reth::cli", url=%addr, "RPC auth server started");
556 }
557 handle
558 });
559
560 let (rpc, auth) = futures::future::try_join(launch_rpc, launch_auth).await?;
562
563 let handles = RethRpcServerHandles { rpc, auth };
564
565 let ctx = RpcContext {
566 node: node.clone(),
567 config,
568 registry: &mut registry,
569 modules: &mut modules,
570 auth_module: &mut auth_module,
571 };
572
573 on_rpc_started.on_rpc_started(ctx, handles.clone())?;
574
575 Ok(RpcHandle {
576 rpc_server_handles: handles,
577 rpc_registry: registry,
578 engine_events,
579 beacon_engine_handle,
580 })
581 }
582}
583
584impl<N, EthB, EV, EB> NodeAddOns<N> for RpcAddOns<N, EthB, EV, EB>
585where
586 N: FullNodeComponents,
587 <N as FullNodeTypes>::Provider: ChainSpecProvider<ChainSpec: EthereumHardforks>,
588 EthB: EthApiBuilder<N>,
589 EV: EngineValidatorBuilder<N>,
590 EB: EngineApiBuilder<N>,
591{
592 type Handle = RpcHandle<N, EthB::EthApi>;
593
594 async fn launch_add_ons(self, ctx: AddOnsContext<'_, N>) -> eyre::Result<Self::Handle> {
595 self.launch_add_ons_with(ctx, |_, _, _| Ok(())).await
596 }
597}
598
599pub trait RethRpcAddOns<N: FullNodeComponents>:
602 NodeAddOns<N, Handle = RpcHandle<N, Self::EthApi>>
603{
604 type EthApi: EthApiTypes;
606
607 fn hooks_mut(&mut self) -> &mut RpcHooks<N, Self::EthApi>;
609}
610
611impl<N: FullNodeComponents, EthB, EV, EB> RethRpcAddOns<N> for RpcAddOns<N, EthB, EV, EB>
612where
613 Self: NodeAddOns<N, Handle = RpcHandle<N, EthB::EthApi>>,
614 EthB: EthApiBuilder<N>,
615{
616 type EthApi = EthB::EthApi;
617
618 fn hooks_mut(&mut self) -> &mut RpcHooks<N, Self::EthApi> {
619 &mut self.hooks
620 }
621}
622
623#[derive(Debug)]
626pub struct EthApiCtx<'a, N: FullNodeTypes> {
627 pub components: &'a N,
629 pub config: EthConfig,
631 pub cache: EthStateCache<BlockTy<N::Types>, ReceiptTy<N::Types>>,
633}
634
635pub trait EthApiBuilder<N: FullNodeComponents>: Default + Send + 'static {
637 type EthApi: EthApiTypes
639 + FullEthApiServer<Provider = N::Provider, Pool = N::Pool>
640 + AddDevSigners
641 + Unpin
642 + 'static;
643
644 fn build_eth_api(
646 self,
647 ctx: EthApiCtx<'_, N>,
648 ) -> impl Future<Output = eyre::Result<Self::EthApi>> + Send;
649}
650
651pub trait EngineValidatorAddOn<Node: FullNodeComponents>: Send {
653 type Validator: EngineValidator<<Node::Types as NodeTypes>::Payload, Block = BlockTy<Node::Types>>
655 + Clone;
656
657 fn engine_validator(
659 &self,
660 ctx: &AddOnsContext<'_, Node>,
661 ) -> impl Future<Output = eyre::Result<Self::Validator>>;
662}
663
664impl<N, EthB, EV, EB> EngineValidatorAddOn<N> for RpcAddOns<N, EthB, EV, EB>
665where
666 N: FullNodeComponents,
667 EthB: EthApiBuilder<N>,
668 EV: EngineValidatorBuilder<N>,
669 EB: EngineApiBuilder<N>,
670{
671 type Validator = EV::Validator;
672
673 async fn engine_validator(&self, ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::Validator> {
674 self.engine_validator_builder.clone().build(ctx).await
675 }
676}
677
678pub trait EngineValidatorBuilder<Node: FullNodeComponents>: Send + Sync + Clone {
680 type Validator: EngineValidator<<Node::Types as NodeTypes>::Payload, Block = BlockTy<Node::Types>>
682 + Clone;
683
684 fn build(
686 self,
687 ctx: &AddOnsContext<'_, Node>,
688 ) -> impl Future<Output = eyre::Result<Self::Validator>> + Send;
689}
690
691impl<Node, F, Fut, Validator> EngineValidatorBuilder<Node> for F
692where
693 Node: FullNodeComponents,
694 Validator: EngineValidator<<Node::Types as NodeTypes>::Payload, Block = BlockTy<Node::Types>>
695 + Clone
696 + Unpin
697 + 'static,
698 F: FnOnce(&AddOnsContext<'_, Node>) -> Fut + Send + Sync + Clone,
699 Fut: Future<Output = eyre::Result<Validator>> + Send,
700{
701 type Validator = Validator;
702
703 fn build(
704 self,
705 ctx: &AddOnsContext<'_, Node>,
706 ) -> impl Future<Output = eyre::Result<Self::Validator>> {
707 self(ctx)
708 }
709}
710
711pub trait EngineApiBuilder<Node: FullNodeComponents>: Send + Sync {
718 type EngineApi: IntoEngineApiRpcModule + Send + Sync;
720
721 fn build_engine_api(
726 self,
727 ctx: &AddOnsContext<'_, Node>,
728 ) -> impl Future<Output = eyre::Result<Self::EngineApi>> + Send;
729}
730
731#[derive(Debug, Default)]
737pub struct BasicEngineApiBuilder<EV> {
738 engine_validator_builder: EV,
739}
740
741impl<N, EV> EngineApiBuilder<N> for BasicEngineApiBuilder<EV>
742where
743 N: FullNodeComponents<
744 Types: NodeTypes<
745 ChainSpec: EthereumHardforks,
746 Payload: PayloadTypes<ExecutionData = ExecutionData> + EngineTypes,
747 >,
748 >,
749 EV: EngineValidatorBuilder<N>,
750{
751 type EngineApi = EngineApi<
752 N::Provider,
753 <N::Types as NodeTypes>::Payload,
754 N::Pool,
755 EV::Validator,
756 <N::Types as NodeTypes>::ChainSpec,
757 >;
758
759 async fn build_engine_api(self, ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::EngineApi> {
760 let Self { engine_validator_builder } = self;
761
762 let engine_validator = engine_validator_builder.build(ctx).await?;
763 let client = ClientVersionV1 {
764 code: CLIENT_CODE,
765 name: NAME_CLIENT.to_string(),
766 version: CARGO_PKG_VERSION.to_string(),
767 commit: VERGEN_GIT_SHA.to_string(),
768 };
769 Ok(EngineApi::new(
770 ctx.node.provider().clone(),
771 ctx.config.chain.clone(),
772 ctx.beacon_engine_handle.clone(),
773 PayloadStore::new(ctx.node.payload_builder_handle().clone()),
774 ctx.node.pool().clone(),
775 Box::new(ctx.node.task_executor().clone()),
776 client,
777 EngineCapabilities::default(),
778 engine_validator,
779 ctx.config.engine.accept_execution_requests_hash,
780 ))
781 }
782}
783
784#[derive(Debug, Clone, Default)]
790#[non_exhaustive]
791pub struct NoopEngineApiBuilder;
792
793impl<N: FullNodeComponents> EngineApiBuilder<N> for NoopEngineApiBuilder {
794 type EngineApi = NoopEngineApi;
795
796 async fn build_engine_api(self, _ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::EngineApi> {
797 Ok(NoopEngineApi::default())
798 }
799}
800
801#[derive(Debug, Clone, Default)]
806#[non_exhaustive]
807pub struct NoopEngineApi;
808
809impl IntoEngineApiRpcModule for NoopEngineApi {
810 fn into_rpc_module(self) -> RpcModule<()> {
811 RpcModule::new(())
812 }
813}