1pub use jsonrpsee::{
4 core::middleware::layer::Either,
5 server::middleware::rpc::{RpcService, RpcServiceBuilder},
6};
7use reth_engine_tree::tree::WaitForCaches;
8pub use reth_engine_tree::tree::{BasicEngineValidator, EngineValidator};
9pub use reth_rpc_builder::{
10 middleware::{RethAuthHttpMiddleware, RethRpcMiddleware},
11 Identity, Stack,
12};
13use reth_storage_overlay::OverlayManager;
14
15use crate::{
16 invalid_block_hook::InvalidBlockHookExt, txpool_prewarm, ConfigureEngineEvm,
17 ConsensusEngineEvent, ConsensusEngineHandle,
18};
19use alloy_rpc_types::engine::ClientVersionV1;
20use alloy_rpc_types_engine::ExecutionData;
21use jsonrpsee::RpcModule;
22use parking_lot::Mutex;
23use reth_chain_state::CanonStateSubscriptions;
24use reth_chainspec::{ChainSpecProvider, EthChainSpec, EthereumHardforks, Hardforks};
25use reth_node_api::{
26 AddOnsContext, BlockTy, EngineApiValidator, EngineTypes, FullNodeComponents, FullNodeTypes,
27 NodeAddOns, NodeTypes, PayloadTypes, PayloadValidator, PrimitivesTy, TreeConfig,
28};
29use reth_node_core::{
30 cli::config::RethTransactionPoolConfig,
31 node_config::NodeConfig,
32 version::{version_metadata, CLIENT_CODE},
33};
34use reth_payload_builder::{PayloadBuilderHandle, PayloadStore};
35use reth_rpc::{
36 eth::{core::EthRpcConverterFor, DevSigner, EthApiTypes, FullEthApiServer},
37 AdminApi,
38};
39use reth_rpc_api::{eth::helpers::EthTransactions, IntoEngineApiRpcModule};
40use reth_rpc_builder::{
41 auth::{AuthRpcModule, AuthServerHandle},
42 config::RethRpcServerConfig,
43 RpcModuleBuilder, RpcRegistryInner, RpcServerConfig, RpcServerHandle, TransportRpcModules,
44};
45use reth_rpc_engine_api::{capabilities::EngineCapabilities, EngineApi};
46use reth_rpc_eth_types::{cache::cache_new_blocks_task, EthConfig, EthStateCache};
47use reth_tokio_util::EventSender;
48use reth_tracing::tracing::{debug, info};
49use std::{
50 fmt::{self, Debug},
51 future::Future,
52 ops::{Deref, DerefMut},
53 sync::Arc,
54};
55use tokio::sync::oneshot;
56
57#[derive(Debug, Clone)]
61pub struct RethRpcServerHandles {
62 pub rpc: RpcServerHandle,
64 pub auth: AuthServerHandle,
66}
67
68pub struct RpcHooks<Node: FullNodeComponents, EthApi> {
70 pub on_rpc_started: Box<dyn OnRpcStarted<Node, EthApi>>,
72 pub extend_rpc_modules: Box<dyn ExtendRpcModules<Node, EthApi>>,
74}
75
76impl<Node, EthApi> Default for RpcHooks<Node, EthApi>
77where
78 Node: FullNodeComponents,
79 EthApi: EthApiTypes,
80{
81 fn default() -> Self {
82 Self { on_rpc_started: Box::<()>::default(), extend_rpc_modules: Box::<()>::default() }
83 }
84}
85
86impl<Node, EthApi> RpcHooks<Node, EthApi>
87where
88 Node: FullNodeComponents,
89 EthApi: EthApiTypes,
90{
91 pub(crate) fn set_on_rpc_started<F>(&mut self, hook: F) -> &mut Self
93 where
94 F: OnRpcStarted<Node, EthApi> + 'static,
95 {
96 self.on_rpc_started = Box::new(hook);
97 self
98 }
99
100 #[expect(unused)]
102 pub(crate) fn on_rpc_started<F>(mut self, hook: F) -> Self
103 where
104 F: OnRpcStarted<Node, EthApi> + 'static,
105 {
106 self.set_on_rpc_started(hook);
107 self
108 }
109
110 pub(crate) fn set_extend_rpc_modules<F>(&mut self, hook: F) -> &mut Self
112 where
113 F: ExtendRpcModules<Node, EthApi> + 'static,
114 {
115 self.extend_rpc_modules = Box::new(hook);
116 self
117 }
118
119 #[expect(unused)]
121 pub(crate) fn extend_rpc_modules<F>(mut self, hook: F) -> Self
122 where
123 F: ExtendRpcModules<Node, EthApi> + 'static,
124 {
125 self.set_extend_rpc_modules(hook);
126 self
127 }
128}
129
130impl<Node, EthApi> fmt::Debug for RpcHooks<Node, EthApi>
131where
132 Node: FullNodeComponents,
133 EthApi: EthApiTypes,
134{
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 f.debug_struct("RpcHooks")
137 .field("on_rpc_started", &"...")
138 .field("extend_rpc_modules", &"...")
139 .finish()
140 }
141}
142
143pub trait OnRpcStarted<Node: FullNodeComponents, EthApi: EthApiTypes>: Send {
145 fn on_rpc_started(
147 self: Box<Self>,
148 ctx: RpcContext<'_, Node, EthApi>,
149 handles: RethRpcServerHandles,
150 ) -> eyre::Result<()>;
151}
152
153impl<Node, EthApi, F> OnRpcStarted<Node, EthApi> for F
154where
155 F: FnOnce(RpcContext<'_, Node, EthApi>, RethRpcServerHandles) -> eyre::Result<()> + Send,
156 Node: FullNodeComponents,
157 EthApi: EthApiTypes,
158{
159 fn on_rpc_started(
160 self: Box<Self>,
161 ctx: RpcContext<'_, Node, EthApi>,
162 handles: RethRpcServerHandles,
163 ) -> eyre::Result<()> {
164 (*self)(ctx, handles)
165 }
166}
167
168impl<Node, EthApi> OnRpcStarted<Node, EthApi> for ()
169where
170 Node: FullNodeComponents,
171 EthApi: EthApiTypes,
172{
173 fn on_rpc_started(
174 self: Box<Self>,
175 _: RpcContext<'_, Node, EthApi>,
176 _: RethRpcServerHandles,
177 ) -> eyre::Result<()> {
178 Ok(())
179 }
180}
181
182pub trait ExtendRpcModules<Node: FullNodeComponents, EthApi: EthApiTypes>: Send {
184 fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()>;
186}
187
188impl<Node, EthApi, F> ExtendRpcModules<Node, EthApi> for F
189where
190 F: FnOnce(RpcContext<'_, Node, EthApi>) -> eyre::Result<()> + Send,
191 Node: FullNodeComponents,
192 EthApi: EthApiTypes,
193{
194 fn extend_rpc_modules(self: Box<Self>, ctx: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> {
195 (*self)(ctx)
196 }
197}
198
199impl<Node, EthApi> ExtendRpcModules<Node, EthApi> for ()
200where
201 Node: FullNodeComponents,
202 EthApi: EthApiTypes,
203{
204 fn extend_rpc_modules(self: Box<Self>, _: RpcContext<'_, Node, EthApi>) -> eyre::Result<()> {
205 Ok(())
206 }
207}
208
209#[derive(Debug, Clone)]
211#[expect(clippy::type_complexity)]
212pub struct RpcRegistry<Node: FullNodeComponents, EthApi: EthApiTypes> {
213 pub(crate) registry: RpcRegistryInner<
214 Node::Provider,
215 Node::Pool,
216 Node::Network,
217 EthApi,
218 Node::Evm,
219 Node::Consensus,
220 >,
221}
222
223impl<Node, EthApi> Deref for RpcRegistry<Node, EthApi>
224where
225 Node: FullNodeComponents,
226 EthApi: EthApiTypes,
227{
228 type Target = RpcRegistryInner<
229 Node::Provider,
230 Node::Pool,
231 Node::Network,
232 EthApi,
233 Node::Evm,
234 Node::Consensus,
235 >;
236
237 fn deref(&self) -> &Self::Target {
238 &self.registry
239 }
240}
241
242impl<Node, EthApi> DerefMut for RpcRegistry<Node, EthApi>
243where
244 Node: FullNodeComponents,
245 EthApi: EthApiTypes,
246{
247 fn deref_mut(&mut self) -> &mut Self::Target {
248 &mut self.registry
249 }
250}
251
252#[expect(missing_debug_implementations)]
254pub struct RpcModuleContainer<'a, Node: FullNodeComponents, EthApi: EthApiTypes> {
255 pub modules: &'a mut TransportRpcModules,
257 pub auth_module: &'a mut AuthRpcModule,
259 pub registry: &'a mut RpcRegistry<Node, EthApi>,
261}
262
263#[expect(missing_debug_implementations)]
271pub struct RpcContext<'a, Node: FullNodeComponents, EthApi: EthApiTypes> {
272 pub(crate) node: Node,
274
275 pub(crate) config: &'a NodeConfig<<Node::Types as NodeTypes>::ChainSpec>,
277
278 pub registry: &'a mut RpcRegistry<Node, EthApi>,
282 pub modules: &'a mut TransportRpcModules,
287 pub auth_module: &'a mut AuthRpcModule,
291}
292
293impl<Node, EthApi> RpcContext<'_, Node, EthApi>
294where
295 Node: FullNodeComponents,
296 EthApi: EthApiTypes,
297{
298 pub const fn config(&self) -> &NodeConfig<<Node::Types as NodeTypes>::ChainSpec> {
300 self.config
301 }
302
303 pub const fn node(&self) -> &Node {
307 &self.node
308 }
309
310 pub fn pool(&self) -> &Node::Pool {
312 self.node.pool()
313 }
314
315 pub fn provider(&self) -> &Node::Provider {
317 self.node.provider()
318 }
319
320 pub fn network(&self) -> &Node::Network {
322 self.node.network()
323 }
324
325 pub fn payload_builder_handle(
327 &self,
328 ) -> &PayloadBuilderHandle<<Node::Types as NodeTypes>::Payload> {
329 self.node.payload_builder_handle()
330 }
331}
332
333pub struct RpcHandle<Node: FullNodeComponents, EthApi: EthApiTypes> {
335 pub rpc_server_handles: RethRpcServerHandles,
337 pub rpc_registry: RpcRegistry<Node, EthApi>,
339 pub engine_events: EventSender<ConsensusEngineEvent<<Node::Types as NodeTypes>::Primitives>>,
344 pub beacon_engine_handle: ConsensusEngineHandle<<Node::Types as NodeTypes>::Payload>,
346 pub engine_shutdown: EngineShutdown,
348}
349
350impl<Node: FullNodeComponents, EthApi: EthApiTypes> Clone for RpcHandle<Node, EthApi> {
351 fn clone(&self) -> Self {
352 Self {
353 rpc_server_handles: self.rpc_server_handles.clone(),
354 rpc_registry: self.rpc_registry.clone(),
355 engine_events: self.engine_events.clone(),
356 beacon_engine_handle: self.beacon_engine_handle.clone(),
357 engine_shutdown: self.engine_shutdown.clone(),
358 }
359 }
360}
361
362impl<Node: FullNodeComponents, EthApi: EthApiTypes> Deref for RpcHandle<Node, EthApi> {
363 type Target = RpcRegistry<Node, EthApi>;
364
365 fn deref(&self) -> &Self::Target {
366 &self.rpc_registry
367 }
368}
369
370impl<Node: FullNodeComponents, EthApi: EthApiTypes> Debug for RpcHandle<Node, EthApi>
371where
372 RpcRegistry<Node, EthApi>: Debug,
373{
374 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
375 f.debug_struct("RpcHandle")
376 .field("rpc_server_handles", &self.rpc_server_handles)
377 .field("rpc_registry", &self.rpc_registry)
378 .field("engine_shutdown", &self.engine_shutdown)
379 .finish()
380 }
381}
382
383impl<Node: FullNodeComponents, EthApi: EthApiTypes> RpcHandle<Node, EthApi> {
384 pub const fn rpc_server_handles(&self) -> &RethRpcServerHandles {
386 &self.rpc_server_handles
387 }
388
389 pub const fn consensus_engine_handle(
393 &self,
394 ) -> &ConsensusEngineHandle<<Node::Types as NodeTypes>::Payload> {
395 &self.beacon_engine_handle
396 }
397
398 pub const fn consensus_engine_events(
400 &self,
401 ) -> &EventSender<ConsensusEngineEvent<<Node::Types as NodeTypes>::Primitives>> {
402 &self.engine_events
403 }
404
405 pub const fn eth_api(&self) -> &EthApi {
407 self.rpc_registry.registry.eth_api()
408 }
409
410 pub fn admin_api(
412 &self,
413 ) -> AdminApi<Node::Network, <Node::Types as NodeTypes>::ChainSpec, Node::Pool>
414 where
415 <Node::Types as NodeTypes>::ChainSpec: EthereumHardforks,
416 {
417 self.rpc_registry.registry.admin_api()
418 }
419}
420
421#[derive(Debug, Clone)]
427pub struct RpcServerOnlyHandle<Node: FullNodeComponents, EthApi: EthApiTypes> {
428 pub rpc_server_handle: RpcServerHandle,
430 pub rpc_registry: RpcRegistry<Node, EthApi>,
432 pub engine_events: EventSender<ConsensusEngineEvent<<Node::Types as NodeTypes>::Primitives>>,
434 pub engine_handle: ConsensusEngineHandle<<Node::Types as NodeTypes>::Payload>,
436}
437
438impl<Node: FullNodeComponents, EthApi: EthApiTypes> RpcServerOnlyHandle<Node, EthApi> {
439 pub const fn rpc_server_handle(&self) -> &RpcServerHandle {
441 &self.rpc_server_handle
442 }
443
444 pub const fn consensus_engine_handle(
448 &self,
449 ) -> &ConsensusEngineHandle<<Node::Types as NodeTypes>::Payload> {
450 &self.engine_handle
451 }
452
453 pub const fn consensus_engine_events(
455 &self,
456 ) -> &EventSender<ConsensusEngineEvent<<Node::Types as NodeTypes>::Primitives>> {
457 &self.engine_events
458 }
459}
460
461#[derive(Debug, Clone)]
467pub struct AuthServerOnlyHandle<Node: FullNodeComponents, EthApi: EthApiTypes> {
468 pub auth_server_handle: AuthServerHandle,
470 pub rpc_registry: RpcRegistry<Node, EthApi>,
472 pub engine_events: EventSender<ConsensusEngineEvent<<Node::Types as NodeTypes>::Primitives>>,
474 pub engine_handle: ConsensusEngineHandle<<Node::Types as NodeTypes>::Payload>,
476}
477
478impl<Node: FullNodeComponents, EthApi: EthApiTypes> AuthServerOnlyHandle<Node, EthApi> {
479 pub const fn consensus_engine_handle(
483 &self,
484 ) -> &ConsensusEngineHandle<<Node::Types as NodeTypes>::Payload> {
485 &self.engine_handle
486 }
487
488 pub const fn consensus_engine_events(
490 &self,
491 ) -> &EventSender<ConsensusEngineEvent<<Node::Types as NodeTypes>::Primitives>> {
492 &self.engine_events
493 }
494}
495
496struct RpcSetupContext<'a, Node: FullNodeComponents, EthApi: EthApiTypes> {
498 node: Node,
499 config: &'a NodeConfig<<Node::Types as NodeTypes>::ChainSpec>,
500 modules: TransportRpcModules,
501 auth_module: AuthRpcModule,
502 auth_config: reth_rpc_builder::auth::AuthServerConfig,
503 registry: RpcRegistry<Node, EthApi>,
504 on_rpc_started: Box<dyn OnRpcStarted<Node, EthApi>>,
505 engine_events: EventSender<ConsensusEngineEvent<<Node::Types as NodeTypes>::Primitives>>,
506 engine_handle: ConsensusEngineHandle<<Node::Types as NodeTypes>::Payload>,
507}
508
509pub struct RpcAddOns<
520 Node: FullNodeComponents,
521 EthB: EthApiBuilder<Node>,
522 PVB,
523 EB = BasicEngineApiBuilder<PVB>,
524 EVB = BasicEngineValidatorBuilder<PVB>,
525 RpcMiddleware = Identity,
526 AuthHttpMiddleware = Identity,
527> {
528 pub hooks: RpcHooks<Node, EthB::EthApi>,
530 eth_api_builder: EthB,
532 payload_validator_builder: PVB,
534 engine_api_builder: EB,
536 engine_validator_builder: EVB,
538 rpc_middleware: RpcMiddleware,
543 auth_http_middleware: AuthHttpMiddleware,
548 tokio_runtime: Option<tokio::runtime::Handle>,
550}
551
552impl<Node, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware> Debug
553 for RpcAddOns<Node, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
554where
555 Node: FullNodeComponents,
556 EthB: EthApiBuilder<Node>,
557 PVB: Debug,
558 EB: Debug,
559 EVB: Debug,
560{
561 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
562 f.debug_struct("RpcAddOns")
563 .field("hooks", &self.hooks)
564 .field("eth_api_builder", &"...")
565 .field("payload_validator_builder", &self.payload_validator_builder)
566 .field("engine_api_builder", &self.engine_api_builder)
567 .field("engine_validator_builder", &self.engine_validator_builder)
568 .field("rpc_middleware", &"...")
569 .finish()
570 }
571}
572
573impl<Node, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
574 RpcAddOns<Node, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
575where
576 Node: FullNodeComponents,
577 EthB: EthApiBuilder<Node>,
578{
579 pub fn new(
581 eth_api_builder: EthB,
582 payload_validator_builder: PVB,
583 engine_api_builder: EB,
584 engine_validator_builder: EVB,
585 rpc_middleware: RpcMiddleware,
586 auth_http_middleware: AuthHttpMiddleware,
587 ) -> Self {
588 Self {
589 hooks: RpcHooks::default(),
590 eth_api_builder,
591 payload_validator_builder,
592 engine_api_builder,
593 engine_validator_builder,
594 rpc_middleware,
595 auth_http_middleware,
596 tokio_runtime: None,
597 }
598 }
599
600 pub fn with_engine_api<T>(
602 self,
603 engine_api_builder: T,
604 ) -> RpcAddOns<Node, EthB, PVB, T, EVB, RpcMiddleware, AuthHttpMiddleware> {
605 self.map_engine_api(|_| engine_api_builder)
606 }
607
608 pub fn map_engine_api<T>(
610 self,
611 f: impl FnOnce(EB) -> T,
612 ) -> RpcAddOns<Node, EthB, PVB, T, EVB, RpcMiddleware, AuthHttpMiddleware> {
613 let Self {
614 hooks,
615 eth_api_builder,
616 payload_validator_builder,
617 engine_api_builder,
618 engine_validator_builder,
619 rpc_middleware,
620 auth_http_middleware,
621 tokio_runtime,
622 } = self;
623 RpcAddOns {
624 hooks,
625 eth_api_builder,
626 payload_validator_builder,
627 engine_api_builder: f(engine_api_builder),
628 engine_validator_builder,
629 rpc_middleware,
630 auth_http_middleware,
631 tokio_runtime,
632 }
633 }
634
635 pub fn with_payload_validator<T>(
637 self,
638 payload_validator_builder: T,
639 ) -> RpcAddOns<Node, EthB, T, EB, EVB, RpcMiddleware, AuthHttpMiddleware> {
640 let Self {
641 hooks,
642 eth_api_builder,
643 engine_api_builder,
644 engine_validator_builder,
645 rpc_middleware,
646 auth_http_middleware,
647 tokio_runtime,
648 ..
649 } = self;
650 RpcAddOns {
651 hooks,
652 eth_api_builder,
653 payload_validator_builder,
654 engine_api_builder,
655 engine_validator_builder,
656 rpc_middleware,
657 auth_http_middleware,
658 tokio_runtime,
659 }
660 }
661
662 pub fn with_engine_validator<T>(
664 self,
665 engine_validator_builder: T,
666 ) -> RpcAddOns<Node, EthB, PVB, EB, T, RpcMiddleware, AuthHttpMiddleware> {
667 let Self {
668 hooks,
669 eth_api_builder,
670 payload_validator_builder,
671 engine_api_builder,
672 rpc_middleware,
673 auth_http_middleware,
674 tokio_runtime,
675 ..
676 } = self;
677 RpcAddOns {
678 hooks,
679 eth_api_builder,
680 payload_validator_builder,
681 engine_api_builder,
682 engine_validator_builder,
683 rpc_middleware,
684 auth_http_middleware,
685 tokio_runtime,
686 }
687 }
688
689 pub fn with_rpc_middleware<T>(
728 self,
729 rpc_middleware: T,
730 ) -> RpcAddOns<Node, EthB, PVB, EB, EVB, T, AuthHttpMiddleware> {
731 let Self {
732 hooks,
733 eth_api_builder,
734 payload_validator_builder,
735 engine_api_builder,
736 engine_validator_builder,
737 auth_http_middleware,
738 tokio_runtime,
739 ..
740 } = self;
741 RpcAddOns {
742 hooks,
743 eth_api_builder,
744 payload_validator_builder,
745 engine_api_builder,
746 engine_validator_builder,
747 rpc_middleware,
748 auth_http_middleware,
749 tokio_runtime,
750 }
751 }
752
753 pub fn with_auth_http_middleware<T>(
758 self,
759 auth_http_middleware: T,
760 ) -> RpcAddOns<Node, EthB, PVB, EB, EVB, RpcMiddleware, T> {
761 let Self {
762 hooks,
763 eth_api_builder,
764 payload_validator_builder,
765 engine_api_builder,
766 engine_validator_builder,
767 rpc_middleware,
768 tokio_runtime,
769 ..
770 } = self;
771 RpcAddOns {
772 hooks,
773 eth_api_builder,
774 payload_validator_builder,
775 engine_api_builder,
776 engine_validator_builder,
777 rpc_middleware,
778 auth_http_middleware,
779 tokio_runtime,
780 }
781 }
782
783 pub fn layer_auth_http_middleware<T>(
785 self,
786 layer: T,
787 ) -> RpcAddOns<Node, EthB, PVB, EB, EVB, RpcMiddleware, Stack<AuthHttpMiddleware, T>> {
788 let Self {
789 hooks,
790 eth_api_builder,
791 payload_validator_builder,
792 engine_api_builder,
793 engine_validator_builder,
794 rpc_middleware,
795 auth_http_middleware,
796 tokio_runtime,
797 } = self;
798 let auth_http_middleware = Stack::new(auth_http_middleware, layer);
799 RpcAddOns {
800 hooks,
801 eth_api_builder,
802 payload_validator_builder,
803 engine_api_builder,
804 engine_validator_builder,
805 rpc_middleware,
806 auth_http_middleware,
807 tokio_runtime,
808 }
809 }
810
811 pub fn map_auth_http_middleware<T>(
813 self,
814 f: impl FnOnce(AuthHttpMiddleware) -> T,
815 ) -> RpcAddOns<Node, EthB, PVB, EB, EVB, RpcMiddleware, T> {
816 let Self {
817 hooks,
818 eth_api_builder,
819 payload_validator_builder,
820 engine_api_builder,
821 engine_validator_builder,
822 rpc_middleware,
823 auth_http_middleware,
824 tokio_runtime,
825 } = self;
826 RpcAddOns {
827 hooks,
828 eth_api_builder,
829 payload_validator_builder,
830 engine_api_builder,
831 engine_validator_builder,
832 rpc_middleware,
833 auth_http_middleware: f(auth_http_middleware),
834 tokio_runtime,
835 }
836 }
837
838 #[expect(clippy::type_complexity)]
840 pub fn option_layer_auth_http_middleware<T>(
841 self,
842 layer: Option<T>,
843 ) -> RpcAddOns<
844 Node,
845 EthB,
846 PVB,
847 EB,
848 EVB,
849 RpcMiddleware,
850 Stack<AuthHttpMiddleware, Either<T, Identity>>,
851 > {
852 let layer = layer.map(Either::Left).unwrap_or(Either::Right(Identity::new()));
853 self.layer_auth_http_middleware(layer)
854 }
855
856 pub fn with_tokio_runtime(self, tokio_runtime: Option<tokio::runtime::Handle>) -> Self {
860 let Self {
861 hooks,
862 eth_api_builder,
863 payload_validator_builder,
864 engine_validator_builder,
865 engine_api_builder,
866 rpc_middleware,
867 auth_http_middleware,
868 ..
869 } = self;
870 Self {
871 hooks,
872 eth_api_builder,
873 payload_validator_builder,
874 engine_validator_builder,
875 engine_api_builder,
876 rpc_middleware,
877 auth_http_middleware,
878 tokio_runtime,
879 }
880 }
881
882 pub fn layer_rpc_middleware<T>(
884 self,
885 layer: T,
886 ) -> RpcAddOns<Node, EthB, PVB, EB, EVB, Stack<RpcMiddleware, T>, AuthHttpMiddleware> {
887 let Self {
888 hooks,
889 eth_api_builder,
890 payload_validator_builder,
891 engine_api_builder,
892 engine_validator_builder,
893 rpc_middleware,
894 auth_http_middleware,
895 tokio_runtime,
896 } = self;
897 let rpc_middleware = Stack::new(rpc_middleware, layer);
898 RpcAddOns {
899 hooks,
900 eth_api_builder,
901 payload_validator_builder,
902 engine_api_builder,
903 engine_validator_builder,
904 rpc_middleware,
905 auth_http_middleware,
906 tokio_runtime,
907 }
908 }
909
910 #[expect(clippy::type_complexity)]
912 pub fn option_layer_rpc_middleware<T>(
913 self,
914 layer: Option<T>,
915 ) -> RpcAddOns<
916 Node,
917 EthB,
918 PVB,
919 EB,
920 EVB,
921 Stack<RpcMiddleware, Either<T, Identity>>,
922 AuthHttpMiddleware,
923 > {
924 let layer = layer.map(Either::Left).unwrap_or(Either::Right(Identity::new()));
925 self.layer_rpc_middleware(layer)
926 }
927
928 pub fn on_rpc_started<F>(mut self, hook: F) -> Self
930 where
931 F: FnOnce(RpcContext<'_, Node, EthB::EthApi>, RethRpcServerHandles) -> eyre::Result<()>
932 + Send
933 + 'static,
934 {
935 self.hooks.set_on_rpc_started(hook);
936 self
937 }
938
939 pub fn extend_rpc_modules<F>(mut self, hook: F) -> Self
941 where
942 F: FnOnce(RpcContext<'_, Node, EthB::EthApi>) -> eyre::Result<()> + Send + 'static,
943 {
944 self.hooks.set_extend_rpc_modules(hook);
945 self
946 }
947}
948
949impl<Node, EthB, EV, EB, Engine> Default
950 for RpcAddOns<Node, EthB, EV, EB, Engine, Identity, Identity>
951where
952 Node: FullNodeComponents,
953 EthB: EthApiBuilder<Node>,
954 EV: Default,
955 EB: Default,
956 Engine: Default,
957{
958 fn default() -> Self {
959 Self::new(
960 EthB::default(),
961 EV::default(),
962 EB::default(),
963 Engine::default(),
964 Default::default(),
965 Identity::new(),
966 )
967 }
968}
969
970impl<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
971 RpcAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
972where
973 N: FullNodeComponents,
974 N::Provider: ChainSpecProvider<ChainSpec: EthereumHardforks>,
975 EthB: EthApiBuilder<N>,
976 EB: EngineApiBuilder<N>,
977 EVB: EngineValidatorBuilder<N>,
978 RpcMiddleware: RethRpcMiddleware,
979 AuthHttpMiddleware: RethAuthHttpMiddleware<Identity>,
980{
981 pub async fn launch_rpc_server<F>(
987 self,
988 ctx: AddOnsContext<'_, N>,
989 ext: F,
990 ) -> eyre::Result<RpcServerOnlyHandle<N, EthB::EthApi>>
991 where
992 F: FnOnce(RpcModuleContainer<'_, N, EthB::EthApi>) -> eyre::Result<()>,
993 {
994 let rpc_middleware = self.rpc_middleware.clone();
995 let tokio_runtime = self.tokio_runtime.clone();
996 let setup_ctx = self.setup_rpc_components(ctx, ext).await?;
997 let RpcSetupContext {
998 node,
999 config,
1000 mut modules,
1001 mut auth_module,
1002 auth_config: _,
1003 mut registry,
1004 on_rpc_started,
1005 engine_events,
1006 engine_handle,
1007 } = setup_ctx;
1008
1009 let server_config = config
1010 .rpc
1011 .rpc_server_config()
1012 .set_rpc_middleware(rpc_middleware)
1013 .with_tokio_runtime(tokio_runtime);
1014 let rpc_server_handle = Self::launch_rpc_server_internal(server_config, &modules).await?;
1015
1016 let handles =
1017 RethRpcServerHandles { rpc: rpc_server_handle.clone(), auth: AuthServerHandle::noop() };
1018 Self::finalize_rpc_setup(
1019 &mut registry,
1020 &mut modules,
1021 &mut auth_module,
1022 &node,
1023 config,
1024 on_rpc_started,
1025 handles,
1026 )?;
1027
1028 Ok(RpcServerOnlyHandle {
1029 rpc_server_handle,
1030 rpc_registry: registry,
1031 engine_events,
1032 engine_handle,
1033 })
1034 }
1035
1036 pub async fn launch_add_ons_with<F>(
1039 self,
1040 ctx: AddOnsContext<'_, N>,
1041 ext: F,
1042 ) -> eyre::Result<RpcHandle<N, EthB::EthApi>>
1043 where
1044 F: FnOnce(RpcModuleContainer<'_, N, EthB::EthApi>) -> eyre::Result<()>,
1045 {
1046 let disable_auth = ctx.config.rpc.disable_auth_server;
1048 self.launch_add_ons_with_opt_engine(ctx, ext, disable_auth).await
1049 }
1050
1051 pub async fn launch_add_ons_with_opt_engine<F>(
1057 self,
1058 ctx: AddOnsContext<'_, N>,
1059 ext: F,
1060 disable_auth: bool,
1061 ) -> eyre::Result<RpcHandle<N, EthB::EthApi>>
1062 where
1063 F: FnOnce(RpcModuleContainer<'_, N, EthB::EthApi>) -> eyre::Result<()>,
1064 {
1065 let rpc_middleware = self.rpc_middleware.clone();
1066 let auth_http_middleware = self.auth_http_middleware.clone();
1067 let tokio_runtime = self.tokio_runtime.clone();
1068 let setup_ctx = self.setup_rpc_components(ctx, ext).await?;
1069 let RpcSetupContext {
1070 node,
1071 config,
1072 mut modules,
1073 mut auth_module,
1074 auth_config,
1075 mut registry,
1076 on_rpc_started,
1077 engine_events,
1078 engine_handle,
1079 } = setup_ctx;
1080
1081 let server_config = config
1082 .rpc
1083 .rpc_server_config()
1084 .set_rpc_middleware(rpc_middleware)
1085 .with_tokio_runtime(tokio_runtime);
1086
1087 let auth_config = auth_config.with_http_middleware(auth_http_middleware);
1088
1089 let (rpc, auth) = if disable_auth {
1090 let rpc = Self::launch_rpc_server_internal(server_config, &modules).await?;
1092 (rpc, AuthServerHandle::noop())
1093 } else {
1094 let auth_module_clone = auth_module.clone();
1095 let (rpc, auth) = futures::future::try_join(
1097 Self::launch_rpc_server_internal(server_config, &modules),
1098 Self::launch_auth_server_internal(auth_config.start(auth_module_clone)),
1099 )
1100 .await?;
1101 (rpc, auth)
1102 };
1103
1104 let handles = RethRpcServerHandles { rpc, auth };
1105
1106 Self::finalize_rpc_setup(
1107 &mut registry,
1108 &mut modules,
1109 &mut auth_module,
1110 &node,
1111 config,
1112 on_rpc_started,
1113 handles.clone(),
1114 )?;
1115
1116 Ok(RpcHandle {
1117 rpc_server_handles: handles,
1118 rpc_registry: registry,
1119 engine_events,
1120 beacon_engine_handle: engine_handle,
1121 engine_shutdown: EngineShutdown::default(),
1122 })
1123 }
1124
1125 async fn setup_rpc_components<'a, F>(
1127 self,
1128 ctx: AddOnsContext<'a, N>,
1129 ext: F,
1130 ) -> eyre::Result<RpcSetupContext<'a, N, EthB::EthApi>>
1131 where
1132 F: FnOnce(RpcModuleContainer<'_, N, EthB::EthApi>) -> eyre::Result<()>,
1133 {
1134 let Self { eth_api_builder, engine_api_builder, hooks, .. } = self;
1135
1136 let engine_api = engine_api_builder.build_engine_api(&ctx).await?;
1137 let AddOnsContext { node, config, beacon_engine_handle, jwt_secret, engine_events } = ctx;
1138
1139 info!(target: "reth::cli", "Engine API handler initialized");
1140
1141 let cache = EthStateCache::spawn_with(
1142 node.provider().clone(),
1143 config.rpc.eth_config().cache,
1144 node.task_executor().clone(),
1145 );
1146
1147 let new_canonical_blocks = node.provider().canonical_state_stream();
1148 let c = cache.clone();
1149 node.task_executor().spawn_critical_task("cache canonical blocks task", async move {
1150 cache_new_blocks_task(c, new_canonical_blocks).await;
1151 });
1152
1153 let eth_config = config.rpc.eth_config().max_batch_size(config.txpool.max_batch_size());
1154 let ctx = EthApiCtx {
1155 components: &node,
1156 config: eth_config,
1157 cache,
1158 engine_handle: beacon_engine_handle.clone(),
1159 };
1160 let eth_api = eth_api_builder.build_eth_api(ctx).await?;
1161
1162 let auth_config = config.rpc.auth_server_config(jwt_secret)?;
1163 let module_config = config.rpc.transport_rpc_module_config();
1164 debug!(target: "reth::cli", http=?module_config.http(), ws=?module_config.ws(), "Using RPC module config");
1165
1166 let (mut modules, mut auth_module, registry) = RpcModuleBuilder::default()
1167 .with_provider(node.provider().clone())
1168 .with_pool(node.pool().clone())
1169 .with_network(node.network().clone())
1170 .with_executor(node.task_executor().clone())
1171 .with_evm_config(node.evm_config().clone())
1172 .with_consensus(node.consensus().clone())
1173 .build_with_auth_server(
1174 module_config,
1175 engine_api,
1176 eth_api,
1177 engine_events.clone(),
1178 beacon_engine_handle.clone(),
1179 );
1180
1181 if config.dev.dev {
1183 let signers = DevSigner::from_mnemonic(config.dev.dev_mnemonic.as_str(), 20);
1184 registry.eth_api().signers().write().extend(signers);
1185 }
1186
1187 let mut registry = RpcRegistry { registry };
1188 let ctx = RpcContext {
1189 node: node.clone(),
1190 config,
1191 registry: &mut registry,
1192 modules: &mut modules,
1193 auth_module: &mut auth_module,
1194 };
1195
1196 let RpcHooks { on_rpc_started, extend_rpc_modules } = hooks;
1197
1198 ext(RpcModuleContainer {
1199 modules: ctx.modules,
1200 auth_module: ctx.auth_module,
1201 registry: ctx.registry,
1202 })?;
1203 extend_rpc_modules.extend_rpc_modules(ctx)?;
1204
1205 Ok(RpcSetupContext {
1206 node,
1207 config,
1208 modules,
1209 auth_module,
1210 auth_config,
1211 registry,
1212 on_rpc_started,
1213 engine_events,
1214 engine_handle: beacon_engine_handle,
1215 })
1216 }
1217
1218 async fn launch_rpc_server_internal<M>(
1220 server_config: RpcServerConfig<M>,
1221 modules: &TransportRpcModules,
1222 ) -> eyre::Result<RpcServerHandle>
1223 where
1224 M: RethRpcMiddleware,
1225 {
1226 let handle = server_config.start(modules).await?;
1227
1228 if let Some(path) = handle.ipc_endpoint() {
1229 info!(target: "reth::cli", %path, "RPC IPC server started");
1230 }
1231 if let Some(addr) = handle.http_local_addr() {
1232 info!(target: "reth::cli", url=%addr, "RPC HTTP server started");
1233 }
1234 if let Some(addr) = handle.ws_local_addr() {
1235 info!(target: "reth::cli", url=%addr, "RPC WS server started");
1236 }
1237
1238 Ok(handle)
1239 }
1240
1241 async fn launch_auth_server_internal(
1243 start_fut: impl Future<Output = Result<AuthServerHandle, reth_rpc_builder::error::RpcError>>,
1244 ) -> eyre::Result<AuthServerHandle> {
1245 start_fut
1246 .await
1247 .map_err(Into::into)
1248 .inspect(|handle| {
1249 let addr = handle.local_addr();
1250 if let Some(ipc_endpoint) = handle.ipc_endpoint() {
1251 info!(target: "reth::cli", url=%addr, ipc_endpoint=%ipc_endpoint, "RPC auth server started");
1252 } else {
1253 info!(target: "reth::cli", url=%addr, "RPC auth server started");
1254 }
1255 })
1256 }
1257
1258 fn finalize_rpc_setup(
1260 registry: &mut RpcRegistry<N, EthB::EthApi>,
1261 modules: &mut TransportRpcModules,
1262 auth_module: &mut AuthRpcModule,
1263 node: &N,
1264 config: &NodeConfig<<N::Types as NodeTypes>::ChainSpec>,
1265 on_rpc_started: Box<dyn OnRpcStarted<N, EthB::EthApi>>,
1266 handles: RethRpcServerHandles,
1267 ) -> eyre::Result<()> {
1268 let ctx = RpcContext { node: node.clone(), config, registry, modules, auth_module };
1269
1270 on_rpc_started.on_rpc_started(ctx, handles)?;
1271 Ok(())
1272 }
1273}
1274
1275impl<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware> NodeAddOns<N>
1276 for RpcAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
1277where
1278 N: FullNodeComponents,
1279 <N as FullNodeTypes>::Provider: ChainSpecProvider<ChainSpec: EthereumHardforks>,
1280 EthB: EthApiBuilder<N>,
1281 PVB: PayloadValidatorBuilder<N>,
1282 EB: EngineApiBuilder<N>,
1283 EVB: EngineValidatorBuilder<N>,
1284 RpcMiddleware: RethRpcMiddleware,
1285 AuthHttpMiddleware: RethAuthHttpMiddleware<Identity>,
1286{
1287 type Handle = RpcHandle<N, EthB::EthApi>;
1288
1289 async fn launch_add_ons(self, ctx: AddOnsContext<'_, N>) -> eyre::Result<Self::Handle> {
1290 self.launch_add_ons_with(ctx, |_| Ok(())).await
1291 }
1292}
1293
1294pub trait RethRpcAddOns<N: FullNodeComponents>:
1297 NodeAddOns<N, Handle = RpcHandle<N, Self::EthApi>>
1298{
1299 type EthApi: EthApiTypes;
1301
1302 fn hooks_mut(&mut self) -> &mut RpcHooks<N, Self::EthApi>;
1304}
1305
1306impl<N: FullNodeComponents, EthB, EV, EB, Engine, RpcMiddleware, AuthHttpMiddleware>
1307 RethRpcAddOns<N> for RpcAddOns<N, EthB, EV, EB, Engine, RpcMiddleware, AuthHttpMiddleware>
1308where
1309 Self: NodeAddOns<N, Handle = RpcHandle<N, EthB::EthApi>>,
1310 EthB: EthApiBuilder<N>,
1311{
1312 type EthApi = EthB::EthApi;
1313
1314 fn hooks_mut(&mut self) -> &mut RpcHooks<N, Self::EthApi> {
1315 &mut self.hooks
1316 }
1317}
1318
1319#[derive(Debug)]
1322pub struct EthApiCtx<'a, N: FullNodeTypes> {
1323 pub components: &'a N,
1325 pub config: EthConfig,
1327 pub cache: EthStateCache<PrimitivesTy<N::Types>>,
1329 pub engine_handle: ConsensusEngineHandle<<N::Types as NodeTypes>::Payload>,
1331}
1332
1333impl<'a, N: FullNodeComponents<Types: NodeTypes<ChainSpec: Hardforks + EthereumHardforks>>>
1334 EthApiCtx<'a, N>
1335{
1336 pub fn eth_api_builder(self) -> reth_rpc::EthApiBuilder<N, EthRpcConverterFor<N>> {
1338 reth_rpc::EthApiBuilder::new_with_components(self.components.clone())
1339 .eth_cache(self.cache)
1340 .task_spawner(self.components.task_executor().clone())
1341 .gas_cap(self.config.rpc_gas_cap.into())
1342 .max_simulate_blocks(self.config.rpc_max_simulate_blocks)
1343 .compute_state_root_for_eth_simulate(self.config.compute_state_root_for_eth_simulate)
1344 .eth_proof_window(self.config.eth_proof_window)
1345 .fee_history_cache_config(self.config.fee_history_cache)
1346 .proof_permits(self.config.proof_permits)
1347 .gas_oracle_config(self.config.gas_oracle)
1348 .max_batch_size(self.config.max_batch_size)
1349 .max_blocking_io_requests(self.config.max_blocking_io_requests)
1350 .pending_block_kind(self.config.pending_block_kind)
1351 .raw_tx_forwarder(self.config.raw_tx_forwarder)
1352 .evm_memory_limit(self.config.rpc_evm_memory_limit)
1353 .force_blob_sidecar_upcasting(self.config.force_blob_sidecar_upcasting)
1354 }
1355}
1356
1357pub trait EthApiBuilder<N: FullNodeComponents>: Default + Send + 'static {
1359 type EthApi: FullEthApiServer<Provider = N::Provider, Pool = N::Pool>;
1361
1362 fn build_eth_api(
1364 self,
1365 ctx: EthApiCtx<'_, N>,
1366 ) -> impl Future<Output = eyre::Result<Self::EthApi>> + Send;
1367}
1368
1369pub trait EngineValidatorAddOn<Node: FullNodeComponents>: Send {
1371 type ValidatorBuilder: EngineValidatorBuilder<Node>;
1373
1374 fn engine_validator_builder(&self) -> Self::ValidatorBuilder;
1376}
1377
1378impl<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware> EngineValidatorAddOn<N>
1379 for RpcAddOns<N, EthB, PVB, EB, EVB, RpcMiddleware, AuthHttpMiddleware>
1380where
1381 N: FullNodeComponents,
1382 EthB: EthApiBuilder<N>,
1383 PVB: Send,
1384 EB: EngineApiBuilder<N>,
1385 EVB: EngineValidatorBuilder<N>,
1386 RpcMiddleware: Send,
1387 AuthHttpMiddleware: Send,
1388{
1389 type ValidatorBuilder = EVB;
1390
1391 fn engine_validator_builder(&self) -> Self::ValidatorBuilder {
1392 self.engine_validator_builder.clone()
1393 }
1394}
1395
1396pub trait EngineApiBuilder<Node: FullNodeComponents>: Send + Sync {
1403 type EngineApi: IntoEngineApiRpcModule + Send + Sync;
1405
1406 fn build_engine_api(
1411 self,
1412 ctx: &AddOnsContext<'_, Node>,
1413 ) -> impl Future<Output = eyre::Result<Self::EngineApi>> + Send;
1414}
1415
1416pub trait PayloadValidatorBuilder<Node: FullNodeComponents>: Send + Sync + Clone {
1421 type Validator: PayloadValidator<<Node::Types as NodeTypes>::Payload>;
1423
1424 fn build(
1429 self,
1430 ctx: &AddOnsContext<'_, Node>,
1431 ) -> impl Future<Output = eyre::Result<Self::Validator>> + Send;
1432}
1433
1434pub trait EngineValidatorBuilder<Node: FullNodeComponents>: Send + Sync + Clone {
1439 type EngineValidator: EngineValidator<<Node::Types as NodeTypes>::Payload, <Node::Types as NodeTypes>::Primitives>
1441 + WaitForCaches;
1442
1443 fn build_tree_validator(
1447 self,
1448 ctx: &AddOnsContext<'_, Node>,
1449 tree_config: TreeConfig,
1450 overlay_manager: OverlayManager<PrimitivesTy<Node::Types>>,
1451 ) -> impl Future<Output = eyre::Result<Self::EngineValidator>> + Send;
1452}
1453
1454#[derive(Debug, Clone)]
1458pub struct BasicEngineValidatorBuilder<EV> {
1459 payload_validator_builder: EV,
1461}
1462
1463impl<EV> BasicEngineValidatorBuilder<EV> {
1464 pub const fn new(payload_validator_builder: EV) -> Self {
1466 Self { payload_validator_builder }
1467 }
1468}
1469
1470impl<EV> Default for BasicEngineValidatorBuilder<EV>
1471where
1472 EV: Default,
1473{
1474 fn default() -> Self {
1475 Self::new(EV::default())
1476 }
1477}
1478
1479impl<Node, EV> EngineValidatorBuilder<Node> for BasicEngineValidatorBuilder<EV>
1480where
1481 Node: FullNodeComponents<
1482 Evm: ConfigureEngineEvm<
1483 <<Node::Types as NodeTypes>::Payload as PayloadTypes>::ExecutionData,
1484 >,
1485 >,
1486 EV: PayloadValidatorBuilder<Node>,
1487 EV::Validator: reth_engine_primitives::PayloadValidator<
1488 <Node::Types as NodeTypes>::Payload,
1489 Block = BlockTy<Node::Types>,
1490 > + Clone,
1491{
1492 type EngineValidator = BasicEngineValidator<Node::Provider, Node::Evm, EV::Validator>;
1493
1494 async fn build_tree_validator(
1495 self,
1496 ctx: &AddOnsContext<'_, Node>,
1497 tree_config: TreeConfig,
1498 overlay_manager: OverlayManager<PrimitivesTy<Node::Types>>,
1499 ) -> eyre::Result<Self::EngineValidator> {
1500 let validator = self.payload_validator_builder.build(ctx).await?;
1501 let data_dir = ctx.config.datadir.clone().resolve_datadir(ctx.config.chain.chain());
1502 let invalid_block_hook = ctx.create_invalid_block_hook(&data_dir).await?;
1503
1504 let txpool_prewarming = tree_config.txpool_prewarming();
1505 let mut validator = BasicEngineValidator::new(
1506 ctx.node.provider().clone(),
1507 std::sync::Arc::new(ctx.node.consensus().clone()),
1508 ctx.node.evm_config().clone(),
1509 validator,
1510 tree_config,
1511 invalid_block_hook,
1512 overlay_manager,
1513 ctx.node.task_executor().clone(),
1514 );
1515
1516 if txpool_prewarming {
1517 validator = validator
1518 .with_txpool_prewarming(txpool_prewarm::Source::new(ctx.node.pool().clone()));
1519 }
1520
1521 Ok(validator)
1522 }
1523}
1524
1525#[derive(Debug, Default)]
1531pub struct BasicEngineApiBuilder<PVB> {
1532 payload_validator_builder: PVB,
1533}
1534
1535impl<N, PVB> EngineApiBuilder<N> for BasicEngineApiBuilder<PVB>
1536where
1537 N: FullNodeComponents<
1538 Types: NodeTypes<
1539 ChainSpec: EthereumHardforks,
1540 Payload: PayloadTypes<ExecutionData = ExecutionData> + EngineTypes,
1541 >,
1542 >,
1543 PVB: PayloadValidatorBuilder<N>,
1544 PVB::Validator: EngineApiValidator<<N::Types as NodeTypes>::Payload>,
1545{
1546 type EngineApi = EngineApi<
1547 N::Provider,
1548 <N::Types as NodeTypes>::Payload,
1549 N::Pool,
1550 PVB::Validator,
1551 <N::Types as NodeTypes>::ChainSpec,
1552 >;
1553
1554 async fn build_engine_api(self, ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::EngineApi> {
1555 let Self { payload_validator_builder } = self;
1556
1557 let engine_validator = payload_validator_builder.build(ctx).await?;
1558 let client = ClientVersionV1 {
1559 code: CLIENT_CODE,
1560 name: version_metadata().name_client.to_string(),
1561 version: version_metadata().cargo_pkg_version.to_string(),
1562 commit: version_metadata().vergen_git_sha.to_string(),
1563 };
1564
1565 Ok(EngineApi::new(
1566 ctx.node.provider().clone(),
1567 ctx.config.chain.clone(),
1568 ctx.beacon_engine_handle.clone(),
1569 PayloadStore::new(ctx.node.payload_builder_handle().clone()),
1570 ctx.node.pool().clone(),
1571 ctx.node.task_executor().clone(),
1572 client,
1573 EngineCapabilities::default(),
1574 engine_validator,
1575 ctx.config.engine.accept_execution_requests_hash,
1576 ctx.node.network().clone(),
1577 ))
1578 }
1579}
1580
1581#[derive(Debug, Clone, Default)]
1587#[non_exhaustive]
1588pub struct NoopEngineApiBuilder;
1589
1590impl<N: FullNodeComponents> EngineApiBuilder<N> for NoopEngineApiBuilder {
1591 type EngineApi = NoopEngineApi;
1592
1593 async fn build_engine_api(self, _ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::EngineApi> {
1594 Ok(NoopEngineApi::default())
1595 }
1596}
1597
1598#[derive(Debug, Clone, Default)]
1603#[non_exhaustive]
1604pub struct NoopEngineApi;
1605
1606impl IntoEngineApiRpcModule for NoopEngineApi {
1607 fn into_rpc_module(self) -> RpcModule<()> {
1608 RpcModule::new(())
1609 }
1610}
1611
1612#[derive(Clone, Debug)]
1617pub struct EngineShutdown {
1618 tx: Arc<Mutex<Option<oneshot::Sender<EngineShutdownRequest>>>>,
1620}
1621
1622impl EngineShutdown {
1623 pub fn new() -> (Self, oneshot::Receiver<EngineShutdownRequest>) {
1625 let (tx, rx) = oneshot::channel();
1626 (Self { tx: Arc::new(Mutex::new(Some(tx))) }, rx)
1627 }
1628
1629 pub fn shutdown(&self) -> Option<oneshot::Receiver<()>> {
1636 let mut guard = self.tx.lock();
1637 let tx = guard.take()?;
1638 let (done_tx, done_rx) = oneshot::channel();
1639 let _ = tx.send(EngineShutdownRequest { done_tx });
1640 Some(done_rx)
1641 }
1642}
1643
1644impl Default for EngineShutdown {
1645 fn default() -> Self {
1646 Self { tx: Arc::new(Mutex::new(None)) }
1647 }
1648}
1649
1650#[derive(Debug)]
1652pub struct EngineShutdownRequest {
1653 pub done_tx: oneshot::Sender<()>,
1655}