1pub mod addons;
7pub mod args;
8pub mod consensus;
9pub mod genesis;
10pub mod network;
11pub mod payload;
12pub mod pool;
13pub mod producer;
14pub mod validator;
15
16use std::sync::Arc;
17
18use alloy_consensus::Header;
19use arb_payload::ArbEngineTypes;
20use arb_primitives::{ArbPrimitives, ArbTransactionSigned};
21use arb_rpc::{
22 ArbApiHandler, ArbApiServer, ArbEthApiBuilder, NitroExecutionApiServer, NitroExecutionHandler,
23};
24use reth_chainspec::ChainSpec;
25use reth_node_builder::{
26 components::{ComponentsBuilder, ConsensusBuilder, ExecutorBuilder},
27 rpc::{BasicEngineApiBuilder, BasicEngineValidatorBuilder, RpcAddOns, RpcContext},
28 BuilderContext, FullNodeComponents, FullNodeTypes, Node, NodeAdapter, NodeTypes,
29};
30use reth_provider::{
31 BlockNumReader, BlockReaderIdExt, DatabaseProviderFactory, HeaderProvider, StateProviderFactory,
32};
33use reth_rpc_eth_api::EthApiTypes;
34use reth_storage_api::{BlockWriter, CanonChainTracker, DBProvider, EthStorage};
35
36use arb_evm::ArbEvmConfig;
37
38use crate::{
39 addons::ArbPayloadValidatorBuilder, args::RollupArgs, consensus::ArbConsensus,
40 network::ArbNetworkBuilder, payload::ArbPayloadServiceBuilder, pool::ArbPoolBuilder,
41 producer::ArbBlockProducer,
42};
43
44pub type ArbAddOns<N> = RpcAddOns<
46 N,
47 ArbEthApiBuilder,
48 ArbPayloadValidatorBuilder,
49 BasicEngineApiBuilder<ArbPayloadValidatorBuilder>,
50 BasicEngineValidatorBuilder<ArbPayloadValidatorBuilder>,
51>;
52
53pub type ArbStorage = EthStorage<ArbTransactionSigned>;
55
56#[derive(Debug, Clone, Default)]
58pub struct ArbNode {
59 pub args: RollupArgs,
61}
62
63impl ArbNode {
64 pub fn new(args: RollupArgs) -> Self {
66 Self { args }
67 }
68
69 pub fn components<N>() -> ComponentsBuilder<
71 N,
72 ArbPoolBuilder,
73 ArbPayloadServiceBuilder,
74 ArbNetworkBuilder,
75 ArbExecutorBuilder,
76 ArbConsensusBuilder,
77 >
78 where
79 N: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = ArbPrimitives>>,
80 {
81 ComponentsBuilder::default()
82 .node_types::<N>()
83 .pool(ArbPoolBuilder)
84 .executor(ArbExecutorBuilder)
85 .payload(ArbPayloadServiceBuilder)
86 .network(ArbNetworkBuilder)
87 .consensus(ArbConsensusBuilder)
88 }
89}
90
91impl NodeTypes for ArbNode {
92 type Primitives = ArbPrimitives;
93 type ChainSpec = ChainSpec;
94 type Storage = ArbStorage;
95 type Payload = ArbEngineTypes;
96}
97
98impl<N> Node<N> for ArbNode
99where
100 N: FullNodeTypes<Types = Self>,
101 N::Provider: DatabaseProviderFactory<
102 ProviderRW: BlockWriter<
103 Block = alloy_consensus::Block<ArbTransactionSigned>,
104 Receipt = arb_primitives::ArbReceipt,
105 > + reth_storage_api::StateWriter<Receipt = arb_primitives::ArbReceipt>
106 + reth_storage_api::TrieWriter
107 + DBProvider,
108 > + CanonChainTracker<Header = Header>,
109{
110 type ComponentsBuilder = ComponentsBuilder<
111 N,
112 ArbPoolBuilder,
113 ArbPayloadServiceBuilder,
114 ArbNetworkBuilder,
115 ArbExecutorBuilder,
116 ArbConsensusBuilder,
117 >;
118
119 type AddOns =
120 ArbAddOns<
121 NodeAdapter<
122 N,
123 <Self::ComponentsBuilder as reth_node_builder::components::NodeComponentsBuilder<
124 N,
125 >>::Components,
126 >,
127 >;
128
129 fn components_builder(&self) -> Self::ComponentsBuilder {
130 Self::components()
131 }
132
133 fn add_ons(&self) -> Self::AddOns {
134 RpcAddOns::new(
135 ArbEthApiBuilder::default(),
136 ArbPayloadValidatorBuilder,
137 BasicEngineApiBuilder::default(),
138 BasicEngineValidatorBuilder::default(),
139 Default::default(),
140 )
141 .extend_rpc_modules(register_arb_rpc)
142 }
143}
144
145#[derive(Debug, Default, Clone, Copy)]
147pub struct ArbExecutorBuilder;
148
149impl<N> ExecutorBuilder<N> for ArbExecutorBuilder
150where
151 N: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = ArbPrimitives>>,
152{
153 type EVM = ArbEvmConfig;
154
155 async fn build_evm(self, ctx: &BuilderContext<N>) -> eyre::Result<Self::EVM> {
156 Ok(ArbEvmConfig::new(ctx.chain_spec()))
157 }
158}
159
160fn register_arb_rpc<N, EthApi>(ctx: RpcContext<'_, N, EthApi>) -> eyre::Result<()>
162where
163 N: FullNodeComponents<
164 Types: NodeTypes<ChainSpec = ChainSpec, Primitives = ArbPrimitives>,
165 Provider: BlockNumReader
166 + BlockReaderIdExt
167 + HeaderProvider
168 + StateProviderFactory
169 + DatabaseProviderFactory<
170 ProviderRW: BlockWriter<
171 Block = alloy_consensus::Block<ArbTransactionSigned>,
172 Receipt = arb_primitives::ArbReceipt,
173 > + reth_storage_api::StateWriter<Receipt = arb_primitives::ArbReceipt>
174 + reth_storage_api::TrieWriter
175 + DBProvider,
176 > + CanonChainTracker<Header = Header>,
177 >,
178 EthApi: EthApiTypes,
179{
180 let arb_api = ArbApiHandler::new(ctx.provider().clone());
181 ctx.modules.merge_configured(arb_api.into_rpc())?;
182
183 let chain_spec: Arc<ChainSpec> = ctx.config().chain.clone();
185 let evm_config = ArbEvmConfig::new(chain_spec.clone());
186 let persist_provider = ctx.provider().clone();
187 let persist_fn =
188 move |sealed: &reth_primitives_traits::SealedBlock<
189 alloy_consensus::Block<ArbTransactionSigned>,
190 >,
191 receipts: Vec<arb_primitives::ArbReceipt>,
192 bundle_state: revm::database::BundleState,
193 hashed_state: reth_trie_common::HashedPostState,
194 trie_updates: reth_trie_common::updates::TrieUpdates| {
195 use alloy_consensus::BlockHeader;
196 use alloy_evm::block::BlockExecutionResult;
197 use reth_execution_types::BlockExecutionOutput;
198 use reth_primitives_traits::RecoveredBlock;
199 use reth_storage_api::{StateWriter, TrieWriter};
200
201 let block_number = sealed.header().number();
202 let recovered = RecoveredBlock::new_sealed(sealed.clone(), vec![]);
203
204 let provider_rw = persist_provider
205 .database_provider_rw()
206 .map_err(|e| arb_rpc::BlockProducerError::Storage(e.to_string()))?;
207
208 provider_rw
210 .insert_block(&recovered)
211 .map_err(|e| arb_rpc::BlockProducerError::Storage(e.to_string()))?;
212
213 let exec_output = BlockExecutionOutput {
215 state: bundle_state,
216 result: BlockExecutionResult {
217 receipts,
218 requests: Default::default(),
219 gas_used: sealed.header().gas_used(),
220 blob_gas_used: 0,
221 },
222 };
223
224 provider_rw
225 .write_state(
226 reth_storage_api::WriteStateInput::Single {
227 outcome: &exec_output,
228 block: block_number,
229 },
230 revm_database::OriginalValuesKnown::No,
231 reth_storage_api::StateWriteConfig::default(),
232 )
233 .map_err(|e| arb_rpc::BlockProducerError::Storage(e.to_string()))?;
234
235 provider_rw
238 .write_hashed_state(&hashed_state.into_sorted())
239 .map_err(|e| arb_rpc::BlockProducerError::Storage(e.to_string()))?;
240
241 provider_rw
243 .write_trie_updates(trie_updates)
244 .map_err(|e| arb_rpc::BlockProducerError::Storage(e.to_string()))?;
245
246 provider_rw
247 .commit()
248 .map_err(|e| arb_rpc::BlockProducerError::Storage(e.to_string()))?;
249
250 let sealed_header =
252 reth_primitives_traits::SealedHeader::new(sealed.header().clone(), sealed.hash());
253 persist_provider.set_canonical_head(sealed_header);
254
255 Ok(())
256 };
257
258 let genesis_block_num = chain_spec.genesis_header().number;
261
262 let block_producer = Arc::new(ArbBlockProducer::new(
263 ctx.provider().clone(),
264 chain_spec,
265 evm_config,
266 persist_fn,
267 ));
268
269 let nitro_exec =
272 NitroExecutionHandler::new(ctx.provider().clone(), block_producer, genesis_block_num);
273 let nitro_rpc = nitro_exec.into_rpc();
274 ctx.modules.merge_configured(nitro_rpc.clone())?;
275 ctx.auth_module.merge_auth_methods(nitro_rpc)?;
276
277 Ok(())
278}
279
280#[derive(Debug, Default, Clone, Copy)]
282pub struct ArbConsensusBuilder;
283
284impl<N> ConsensusBuilder<N> for ArbConsensusBuilder
285where
286 N: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = ArbPrimitives>>,
287{
288 type Consensus = Arc<ArbConsensus<ChainSpec>>;
289
290 async fn build_consensus(self, ctx: &BuilderContext<N>) -> eyre::Result<Self::Consensus> {
291 Ok(Arc::new(ArbConsensus::new(ctx.chain_spec())))
292 }
293}