reth_node_builder/
node.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
// re-export the node api types
pub use reth_node_api::{FullNodeTypes, NodeTypes, NodeTypesWithEngine};

use std::{
    marker::PhantomData,
    ops::{Deref, DerefMut},
    sync::Arc,
};

use reth_network::NetworkPrimitives;
use reth_node_api::{BlockBody, EngineTypes, FullNodeComponents};
use reth_node_core::{
    dirs::{ChainPath, DataDirPath},
    node_config::NodeConfig,
};
use reth_payload_builder::PayloadBuilderHandle;
use reth_provider::{BlockReader, ChainSpecProvider};
use reth_rpc_api::EngineApiClient;
use reth_rpc_builder::{auth::AuthServerHandle, RpcServerHandle};
use reth_tasks::TaskExecutor;

use crate::{components::NodeComponentsBuilder, rpc::RethRpcAddOns, NodeAdapter, NodeAddOns};

/// A [`crate::Node`] is a [`NodeTypesWithEngine`] that comes with preconfigured components.
///
/// This can be used to configure the builder with a preset of components.
pub trait Node<N: FullNodeTypes>: NodeTypesWithEngine + Clone {
    /// The type that builds the node's components.
    type ComponentsBuilder: NodeComponentsBuilder<N>;

    /// Exposes the customizable node add-on types.
    type AddOns: NodeAddOns<
        NodeAdapter<N, <Self::ComponentsBuilder as NodeComponentsBuilder<N>>::Components>,
    >;

    /// Returns a [`NodeComponentsBuilder`] for the node.
    fn components_builder(&self) -> Self::ComponentsBuilder;

    /// Returns the node add-ons.
    fn add_ons(&self) -> Self::AddOns;
}

/// A [`Node`] type builder
#[derive(Clone, Default, Debug)]
pub struct AnyNode<N = (), C = (), AO = ()>(PhantomData<N>, C, AO);

impl<N, C, AO> AnyNode<N, C, AO> {
    /// Configures the types of the node.
    pub fn types<T>(self) -> AnyNode<T, C, AO> {
        AnyNode(PhantomData, self.1, self.2)
    }

    /// Sets the node components builder.
    pub fn components_builder<T>(self, value: T) -> AnyNode<N, T, AO> {
        AnyNode(PhantomData, value, self.2)
    }

    /// Sets the node add-ons.
    pub fn add_ons<T>(self, value: T) -> AnyNode<N, C, T> {
        AnyNode(PhantomData, self.1, value)
    }
}

impl<N, C, AO> NodeTypes for AnyNode<N, C, AO>
where
    N: FullNodeTypes,
    C: Send + Sync + Unpin + 'static,
    AO: Send + Sync + Unpin + Clone + 'static,
{
    type Primitives = <N::Types as NodeTypes>::Primitives;

    type ChainSpec = <N::Types as NodeTypes>::ChainSpec;

    type StateCommitment = <N::Types as NodeTypes>::StateCommitment;

    type Storage = <N::Types as NodeTypes>::Storage;
}

impl<N, C, AO> NodeTypesWithEngine for AnyNode<N, C, AO>
where
    N: FullNodeTypes,
    C: Send + Sync + Unpin + 'static,
    AO: Send + Sync + Unpin + Clone + 'static,
{
    type Engine = <N::Types as NodeTypesWithEngine>::Engine;
}

impl<N, C, AO> Node<N> for AnyNode<N, C, AO>
where
    N: FullNodeTypes + Clone,
    C: NodeComponentsBuilder<N> + Clone + Sync + Unpin + 'static,
    AO: NodeAddOns<NodeAdapter<N, C::Components>> + Clone + Sync + Unpin + 'static,
{
    type ComponentsBuilder = C;
    type AddOns = AO;

    fn components_builder(&self) -> Self::ComponentsBuilder {
        self.1.clone()
    }

    fn add_ons(&self) -> Self::AddOns {
        self.2.clone()
    }
}

/// The launched node with all components including RPC handlers.
///
/// This can be used to interact with the launched node.
#[derive(Debug)]
pub struct FullNode<Node: FullNodeComponents, AddOns: NodeAddOns<Node>> {
    /// The evm configuration.
    pub evm_config: Node::Evm,
    /// The executor of the node.
    pub block_executor: Node::Executor,
    /// The node's transaction pool.
    pub pool: Node::Pool,
    /// Handle to the node's network.
    pub network: Node::Network,
    /// Provider to interact with the node's database
    pub provider: Node::Provider,
    /// Handle to the node's payload builder service.
    pub payload_builder: PayloadBuilderHandle<<Node::Types as NodeTypesWithEngine>::Engine>,
    /// Task executor for the node.
    pub task_executor: TaskExecutor,
    /// The initial node config.
    pub config: NodeConfig<<Node::Types as NodeTypes>::ChainSpec>,
    /// The data dir of the node.
    pub data_dir: ChainPath<DataDirPath>,
    /// The handle to launched add-ons
    pub add_ons_handle: AddOns::Handle,
}

impl<Node: FullNodeComponents, AddOns: NodeAddOns<Node>> Clone for FullNode<Node, AddOns> {
    fn clone(&self) -> Self {
        Self {
            evm_config: self.evm_config.clone(),
            block_executor: self.block_executor.clone(),
            pool: self.pool.clone(),
            network: self.network.clone(),
            provider: self.provider.clone(),
            payload_builder: self.payload_builder.clone(),
            task_executor: self.task_executor.clone(),
            config: self.config.clone(),
            data_dir: self.data_dir.clone(),
            add_ons_handle: self.add_ons_handle.clone(),
        }
    }
}

impl<Engine, Node, AddOns> FullNode<Node, AddOns>
where
    Engine: EngineTypes,
    Node: FullNodeComponents<Types: NodeTypesWithEngine<Engine = Engine>>,
    AddOns: NodeAddOns<Node>,
{
    /// Returns the chain spec of the node.
    pub fn chain_spec(&self) -> Arc<<Node::Types as NodeTypes>::ChainSpec> {
        self.provider.chain_spec()
    }
}

impl<Engine, Node, AddOns> FullNode<Node, AddOns>
where
    Engine: EngineTypes,
    Node: FullNodeComponents<Types: NodeTypesWithEngine<Engine = Engine>>,
    AddOns: RethRpcAddOns<Node>,
{
    /// Returns the [`RpcServerHandle`] to the started rpc server.
    pub const fn rpc_server_handle(&self) -> &RpcServerHandle {
        &self.add_ons_handle.rpc_server_handles.rpc
    }

    /// Returns the [`AuthServerHandle`] to the started authenticated engine API server.
    pub const fn auth_server_handle(&self) -> &AuthServerHandle {
        &self.add_ons_handle.rpc_server_handles.auth
    }

    /// Returns the [`EngineApiClient`] interface for the authenticated engine API.
    ///
    /// This will send authenticated http requests to the node's auth server.
    pub fn engine_http_client(&self) -> impl EngineApiClient<Engine> {
        self.auth_server_handle().http_client()
    }

    /// Returns the [`EngineApiClient`] interface for the authenticated engine API.
    ///
    /// This will send authenticated ws requests to the node's auth server.
    pub async fn engine_ws_client(&self) -> impl EngineApiClient<Engine> {
        self.auth_server_handle().ws_client().await
    }

    /// Returns the [`EngineApiClient`] interface for the authenticated engine API.
    ///
    /// This will send not authenticated IPC requests to the node's auth server.
    #[cfg(unix)]
    pub async fn engine_ipc_client(&self) -> Option<impl EngineApiClient<Engine>> {
        self.auth_server_handle().ipc_client().await
    }
}

impl<Node: FullNodeComponents, AddOns: NodeAddOns<Node>> Deref for FullNode<Node, AddOns> {
    type Target = AddOns::Handle;

    fn deref(&self) -> &Self::Target {
        &self.add_ons_handle
    }
}

impl<Node: FullNodeComponents, AddOns: NodeAddOns<Node>> DerefMut for FullNode<Node, AddOns> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.add_ons_handle
    }
}

/// This is a type alias to make type bounds simpler, when we have a [`NetworkPrimitives`] and need
/// a [`BlockReader`] whose associated types match the [`NetworkPrimitives`] associated types.
pub trait BlockReaderFor<N: NetworkPrimitives>:
    BlockReader<
    Block = N::Block,
    Header = N::BlockHeader,
    Transaction = <N::BlockBody as BlockBody>::Transaction,
    Receipt = N::Receipt,
>
{
}

impl<N, T> BlockReaderFor<N> for T
where
    N: NetworkPrimitives,
    T: BlockReader<
        Block = N::Block,
        Header = N::BlockHeader,
        Transaction = <N::BlockBody as BlockBody>::Transaction,
        Receipt = N::Receipt,
    >,
{
}