reth_exex/
context.rs
1use crate::{ExExContextDyn, ExExEvent, ExExNotifications, ExExNotificationsStream};
2use alloy_eips::BlockNumHash;
3use reth_exex_types::ExExHead;
4use reth_node_api::{FullNodeComponents, NodePrimitives, NodeTypes, PrimitivesTy};
5use reth_node_core::node_config::NodeConfig;
6use reth_payload_builder::PayloadBuilderHandle;
7use reth_provider::BlockReader;
8use reth_tasks::TaskExecutor;
9use std::fmt::Debug;
10use tokio::sync::mpsc::{error::SendError, UnboundedSender};
11
12pub struct ExExContext<Node: FullNodeComponents> {
16 pub head: BlockNumHash,
18 pub config: NodeConfig<<Node::Types as NodeTypes>::ChainSpec>,
20 pub reth_config: reth_config::Config,
22 pub events: UnboundedSender<ExExEvent>,
30 pub notifications: ExExNotifications<Node::Provider, Node::Executor>,
37
38 pub components: Node,
40}
41
42impl<Node> Debug for ExExContext<Node>
43where
44 Node: FullNodeComponents,
45 Node::Provider: Debug,
46 Node::Executor: Debug,
47{
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 f.debug_struct("ExExContext")
50 .field("head", &self.head)
51 .field("config", &self.config)
52 .field("reth_config", &self.reth_config)
53 .field("events", &self.events)
54 .field("notifications", &self.notifications)
55 .field("components", &"...")
56 .finish()
57 }
58}
59
60impl<Node> ExExContext<Node>
61where
62 Node: FullNodeComponents,
63 Node::Provider: Debug + BlockReader,
64 Node::Executor: Debug,
65 Node::Types: NodeTypes<Primitives: NodePrimitives>,
66{
67 pub fn into_dyn(self) -> ExExContextDyn<PrimitivesTy<Node::Types>> {
69 ExExContextDyn::from(self)
70 }
71}
72
73impl<Node> ExExContext<Node>
74where
75 Node: FullNodeComponents,
76 Node::Types: NodeTypes<Primitives: NodePrimitives>,
77{
78 pub fn pool(&self) -> &Node::Pool {
80 self.components.pool()
81 }
82
83 pub fn evm_config(&self) -> &Node::Evm {
85 self.components.evm_config()
86 }
87
88 pub fn block_executor(&self) -> &Node::Executor {
90 self.components.block_executor()
91 }
92
93 pub fn provider(&self) -> &Node::Provider {
95 self.components.provider()
96 }
97
98 pub fn network(&self) -> &Node::Network {
100 self.components.network()
101 }
102
103 pub fn payload_builder_handle(
105 &self,
106 ) -> &PayloadBuilderHandle<<Node::Types as NodeTypes>::Payload> {
107 self.components.payload_builder_handle()
108 }
109
110 pub fn task_executor(&self) -> &TaskExecutor {
114 self.components.task_executor()
115 }
116
117 pub fn set_notifications_without_head(&mut self) {
120 self.notifications.set_without_head();
121 }
122
123 pub fn set_notifications_with_head(&mut self, head: ExExHead) {
126 self.notifications.set_with_head(head);
127 }
128
129 pub fn send_finished_height(
134 &self,
135 height: BlockNumHash,
136 ) -> Result<(), SendError<BlockNumHash>> {
137 self.events.send(ExExEvent::FinishedHeight(height)).map_err(|_| SendError(height))
138 }
139}
140
141#[cfg(test)]
142mod tests {
143 use crate::ExExContext;
144 use reth_exex_types::ExExHead;
145 use reth_node_api::FullNodeComponents;
146 use reth_provider::BlockReader;
147
148 #[test]
150 const fn issue_12054() {
151 #[expect(dead_code)]
152 struct ExEx<Node: FullNodeComponents> {
153 ctx: ExExContext<Node>,
154 }
155
156 impl<Node: FullNodeComponents> ExEx<Node>
157 where
158 Node::Provider: BlockReader,
159 {
160 async fn _test_bounds(mut self) -> eyre::Result<()> {
161 self.ctx.pool();
162 self.ctx.block_executor();
163 self.ctx.provider();
164 self.ctx.network();
165 self.ctx.payload_builder_handle();
166 self.ctx.task_executor();
167 self.ctx.set_notifications_without_head();
168 self.ctx.set_notifications_with_head(ExExHead { block: Default::default() });
169 Ok(())
170 }
171 }
172 }
173}