arb_node/
lib.rs

1//! Arbitrum node builder.
2//!
3//! Provides the node type definition and component builders
4//! needed to launch an Arbitrum reth node.
5
6pub mod addons;
7pub mod args;
8pub mod chainspec;
9pub mod coalesced_state;
10pub mod consensus;
11pub mod engine;
12pub mod genesis;
13pub mod launcher;
14pub mod network;
15pub mod payload;
16pub mod pool;
17pub mod producer;
18pub mod validator;
19
20use std::sync::Arc;
21
22use alloy_consensus::Header;
23use arb_payload::ArbEngineTypes;
24use arb_primitives::{ArbPrimitives, ArbTransactionSigned};
25use arb_rpc::{
26    stylus_debug::{StylusDebugHandler, StylusDebugServer},
27    ArbApiHandler, ArbApiServer, ArbEthApiBuilder, NitroExecutionApiServer, NitroExecutionHandler,
28};
29use reth_chain_state::CanonicalInMemoryState;
30use reth_chainspec::ChainSpec;
31use reth_node_builder::{
32    components::{ComponentsBuilder, ConsensusBuilder, ExecutorBuilder},
33    rpc::{BasicEngineApiBuilder, BasicEngineValidatorBuilder, RpcAddOns, RpcContext},
34    BuilderContext, FullNodeComponents, FullNodeTypes, Node, NodeAdapter, NodeTypes,
35};
36use reth_provider::{BlockNumReader, BlockReaderIdExt, HeaderProvider, StateProviderFactory};
37use reth_storage_api::{CanonChainTracker, EthStorage};
38
39use arb_evm::ArbEvmConfig;
40
41use crate::{
42    addons::ArbPayloadValidatorBuilder,
43    args::RollupArgs,
44    consensus::ArbConsensus,
45    network::ArbNetworkBuilder,
46    payload::ArbPayloadServiceBuilder,
47    pool::ArbPoolBuilder,
48    producer::{ArbBlockProducer, InMemoryStateAccess},
49};
50
51/// Arbitrum RPC add-ons type alias.
52pub type ArbAddOns<N> = RpcAddOns<
53    N,
54    ArbEthApiBuilder,
55    ArbPayloadValidatorBuilder,
56    BasicEngineApiBuilder<ArbPayloadValidatorBuilder>,
57    BasicEngineValidatorBuilder<ArbPayloadValidatorBuilder>,
58>;
59
60/// Arbitrum storage type.
61pub type ArbStorage = EthStorage<ArbTransactionSigned>;
62
63/// Arbitrum node configuration.
64#[derive(Debug, Clone, Default)]
65pub struct ArbNode {
66    /// Rollup CLI arguments.
67    pub args: RollupArgs,
68}
69
70impl ArbNode {
71    /// Create a new Arbitrum node configuration.
72    pub fn new(args: RollupArgs) -> Self {
73        Self { args }
74    }
75
76    /// Returns a [`ComponentsBuilder`] configured for Arbitrum.
77    pub fn components<N>() -> ComponentsBuilder<
78        N,
79        ArbPoolBuilder,
80        ArbPayloadServiceBuilder,
81        ArbNetworkBuilder,
82        ArbExecutorBuilder,
83        ArbConsensusBuilder,
84    >
85    where
86        N: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = ArbPrimitives>>,
87    {
88        ComponentsBuilder::default()
89            .node_types::<N>()
90            .pool(ArbPoolBuilder)
91            .executor(ArbExecutorBuilder)
92            .payload(ArbPayloadServiceBuilder)
93            .network(ArbNetworkBuilder)
94            .consensus(ArbConsensusBuilder)
95    }
96}
97
98impl NodeTypes for ArbNode {
99    type Primitives = ArbPrimitives;
100    type ChainSpec = ChainSpec;
101    type Storage = ArbStorage;
102    type Payload = ArbEngineTypes;
103}
104
105impl<N> Node<N> for ArbNode
106where
107    N: FullNodeTypes<Types = Self>,
108    N::Provider:
109        CanonChainTracker<Header = Header> + InMemoryStateAccess<Primitives = ArbPrimitives>,
110{
111    type ComponentsBuilder = ComponentsBuilder<
112        N,
113        ArbPoolBuilder,
114        ArbPayloadServiceBuilder,
115        ArbNetworkBuilder,
116        ArbExecutorBuilder,
117        ArbConsensusBuilder,
118    >;
119
120    type AddOns =
121        ArbAddOns<
122            NodeAdapter<
123                N,
124                <Self::ComponentsBuilder as reth_node_builder::components::NodeComponentsBuilder<
125                    N,
126                >>::Components,
127            >,
128        >;
129
130    fn components_builder(&self) -> Self::ComponentsBuilder {
131        Self::components()
132    }
133
134    fn add_ons(&self) -> Self::AddOns {
135        RpcAddOns::new(
136            ArbEthApiBuilder::default(),
137            ArbPayloadValidatorBuilder,
138            BasicEngineApiBuilder::default(),
139            BasicEngineValidatorBuilder::default(),
140            Default::default(),
141        )
142        .extend_rpc_modules(register_arb_rpc)
143    }
144}
145
146/// Builder for the Arbitrum EVM executor component.
147#[derive(Debug, Default, Clone, Copy)]
148pub struct ArbExecutorBuilder;
149
150impl<N> ExecutorBuilder<N> for ArbExecutorBuilder
151where
152    N: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = ArbPrimitives>>,
153{
154    type EVM = ArbEvmConfig;
155
156    async fn build_evm(self, ctx: &BuilderContext<N>) -> eyre::Result<Self::EVM> {
157        Ok(ArbEvmConfig::new(ctx.chain_spec()))
158    }
159}
160
161/// Registers the `arb_` and `nitroexecution_` RPC namespaces.
162fn register_arb_rpc<N, EthApi>(ctx: RpcContext<'_, N, EthApi>) -> eyre::Result<()>
163where
164    N: FullNodeComponents<
165        Types: NodeTypes<ChainSpec = ChainSpec, Primitives = ArbPrimitives>,
166        Provider: BlockNumReader
167                      + BlockReaderIdExt
168                      + HeaderProvider
169                      + StateProviderFactory
170                      + InMemoryStateAccess<Primitives = ArbPrimitives>
171                      + CanonChainTracker<Header = Header>,
172    >,
173    EthApi: reth_rpc_eth_api::FullEthApiTypes
174        + reth_rpc_eth_api::helpers::TraceExt
175        + Clone
176        + Send
177        + Sync
178        + 'static,
179{
180    let arb_api = ArbApiHandler::new(ctx.provider().clone());
181    ctx.modules.merge_configured(arb_api.into_rpc())?;
182
183    // Override debug_traceTransaction so the `stylusTracer` named
184    // option returns the cached host-I/O records; everything else
185    // forwards to the standard handler.
186    {
187        let debug_api = ctx.registry.debug_api();
188        let forwarder: arb_rpc::stylus_debug::DebugForwarder =
189            std::sync::Arc::new(move |tx_hash, opts| {
190                let api = debug_api.clone();
191                Box::pin(async move {
192                    api.debug_trace_transaction(tx_hash, opts.unwrap_or_default())
193                        .await
194                        .map_err(Into::into)
195                })
196            });
197        let stylus_debug = StylusDebugHandler::new(forwarder);
198        ctx.modules
199            .add_or_replace_configured(stylus_debug.into_rpc())?;
200    }
201
202    let chain_spec: Arc<ChainSpec> = ctx.config().chain.clone();
203    let evm_config = ArbEvmConfig::new(chain_spec.clone());
204
205    let in_memory_state: CanonicalInMemoryState<ArbPrimitives> =
206        ctx.provider().canonical_in_memory_state();
207
208    let genesis_block_num = chain_spec.genesis_header().number;
209
210    let flush_interval = std::env::var("ARB_FLUSH_INTERVAL")
211        .ok()
212        .and_then(|v| v.parse().ok())
213        .unwrap_or(producer::DEFAULT_FLUSH_INTERVAL);
214
215    let block_producer = Arc::new(ArbBlockProducer::new(
216        ctx.provider().clone(),
217        chain_spec,
218        evm_config,
219        in_memory_state,
220        flush_interval,
221    ));
222
223    let nitro_exec =
224        NitroExecutionHandler::new(ctx.provider().clone(), block_producer, genesis_block_num);
225    let nitro_rpc = nitro_exec.into_rpc();
226    ctx.modules.merge_configured(nitro_rpc.clone())?;
227    ctx.auth_module.merge_auth_methods(nitro_rpc)?;
228
229    Ok(())
230}
231
232/// Builder for the Arbitrum consensus component.
233#[derive(Debug, Default, Clone, Copy)]
234pub struct ArbConsensusBuilder;
235
236impl<N> ConsensusBuilder<N> for ArbConsensusBuilder
237where
238    N: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = ArbPrimitives>>,
239{
240    type Consensus = Arc<ArbConsensus<ChainSpec>>;
241
242    async fn build_consensus(self, ctx: &BuilderContext<N>) -> eyre::Result<Self::Consensus> {
243        Ok(Arc::new(ArbConsensus::new(ctx.chain_spec())))
244    }
245}