1use crate::{
4 engine::{SeismicEngineTypes, SeismicEngineValidator},
5 txpool::SeismicTransactionPool,
6};
7use alloy_eips::merge::EPOCH_SLOTS;
8use reth_chainspec::{ChainSpec, EthChainSpec};
9use reth_consensus::{ConsensusError, FullConsensus};
10use reth_evm::{ConfigureEvm, EvmFactory, EvmFactoryFor, NextBlockEnvAttributes};
11use reth_network::{NetworkHandle, NetworkPrimitives};
12use reth_node_api::{AddOnsContext, FullNodeComponents, NodeAddOns, PrimitivesTy, TxTy};
13use reth_node_builder::{
14 components::{
15 BasicPayloadServiceBuilder, ComponentsBuilder, ConsensusBuilder, ExecutorBuilder,
16 NetworkBuilder, PayloadBuilderBuilder, PoolBuilder,
17 },
18 node::{FullNodeTypes, NodeTypes},
19 rpc::{
20 EngineValidatorAddOn, EngineValidatorBuilder, EthApiBuilder, RethRpcAddOns, RpcAddOns,
21 RpcHandle,
22 },
23 BuilderContext, DebugNode, Node, NodeAdapter, NodeComponentsBuilder, PayloadBuilderConfig,
24};
25use reth_node_ethereum::consensus::EthBeaconConsensus;
26use reth_provider::{providers::ProviderFactoryBuilder, CanonStateSubscriptions, EthStorage};
27use reth_rpc::ValidationApi;
28use reth_rpc_api::BlockSubmissionValidationApiServer;
29use reth_rpc_builder::config::RethRpcServerConfig;
30use reth_rpc_eth_api::FullEthApiServer;
31use reth_rpc_eth_types::{error::FromEvmError, EthApiError};
32use reth_rpc_server_types::RethRpcModule;
33use reth_seismic_evm::SeismicEvmConfig;
34use reth_seismic_payload_builder::SeismicBuilderConfig;
35use reth_seismic_primitives::{SeismicPrimitives, SeismicReceipt, SeismicTransactionSigned};
36use reth_seismic_rpc::{SeismicEthApi, SeismicEthApiBuilder};
37use reth_transaction_pool::{
38 blobstore::{DiskFileBlobStore, DiskFileBlobStoreConfig},
39 CoinbaseTipOrdering, PoolTransaction, TransactionPool, TransactionValidationTaskExecutor,
40};
41use reth_trie_db::MerklePatriciaTrie;
42use revm::context::TxEnv;
43use seismic_alloy_consensus::SeismicTxEnvelope;
44use seismic_enclave::rpc::SyncEnclaveApiClientBuilder;
45use std::{sync::Arc, time::SystemTime};
46
47use crate::{real_seismic_evm_config, RealSeismicEvmConfig};
48
49pub type SeismicStorage = EthStorage<SeismicTransactionSigned>;
51
52#[derive(Debug, Default, Clone)]
53#[non_exhaustive]
54pub struct SeismicNode;
56
57impl SeismicNode {
58 pub fn components<Node>(
60 &self,
61 ) -> ComponentsBuilder<
62 Node,
63 SeismicPoolBuilder,
64 BasicPayloadServiceBuilder<SeismicPayloadBuilder>,
65 SeismicNetworkBuilder,
66 SeismicExecutorBuilder,
67 SeismicConsensusBuilder,
68 >
69 where
70 Node: FullNodeTypes<
71 Types: NodeTypes<
72 Payload = SeismicEngineTypes,
73 ChainSpec = ChainSpec,
74 Primitives = SeismicPrimitives,
75 >,
76 >,
77 {
78 ComponentsBuilder::default()
79 .node_types::<Node>()
80 .pool(SeismicPoolBuilder::default())
81 .executor(SeismicExecutorBuilder::default())
82 .payload(BasicPayloadServiceBuilder::<SeismicPayloadBuilder>::default())
83 .network(SeismicNetworkBuilder::default())
84 .executor(SeismicExecutorBuilder::default())
85 .consensus(SeismicConsensusBuilder::default())
86 }
87
88 pub fn provider_factory_builder() -> ProviderFactoryBuilder<Self> {
120 ProviderFactoryBuilder::default()
121 }
122}
123
124impl<N> Node<N> for SeismicNode
125where
126 N: FullNodeTypes<
127 Types: NodeTypes<
128 Payload = SeismicEngineTypes,
129 ChainSpec = ChainSpec,
130 Primitives = SeismicPrimitives,
131 Storage = SeismicStorage,
132 >,
133 >,
134{
135 type ComponentsBuilder = ComponentsBuilder<
136 N,
137 SeismicPoolBuilder,
138 BasicPayloadServiceBuilder<SeismicPayloadBuilder>,
139 SeismicNetworkBuilder,
140 SeismicExecutorBuilder,
141 SeismicConsensusBuilder,
142 >;
143
144 type AddOns = SeismicAddOns<
145 NodeAdapter<N, <Self::ComponentsBuilder as NodeComponentsBuilder<N>>::Components>,
146 >;
147
148 fn components_builder(&self) -> Self::ComponentsBuilder {
149 Self::components(self)
150 }
151
152 fn add_ons(&self) -> Self::AddOns {
153 Self::AddOns::builder().build()
154 }
155}
156
157impl NodeTypes for SeismicNode {
158 type Primitives = SeismicPrimitives;
159 type ChainSpec = ChainSpec;
160 type StateCommitment = MerklePatriciaTrie;
161 type Storage = SeismicStorage;
162 type Payload = SeismicEngineTypes;
163}
164
165impl<N> DebugNode<N> for SeismicNode
166where
167 N: FullNodeComponents<Types = Self>,
168{
169 type RpcBlock = alloy_rpc_types_eth::Block<seismic_alloy_consensus::SeismicTxEnvelope>;
170
171 fn rpc_to_primitive_block(rpc_block: Self::RpcBlock) -> reth_node_api::BlockTy<Self> {
172 let alloy_rpc_types_eth::Block { header, transactions, .. } = rpc_block;
173 reth_seismic_primitives::SeismicBlock {
174 header: header.inner,
175 body: reth_seismic_primitives::SeismicBlockBody {
176 transactions: transactions.into_transactions().map(Into::into).collect(),
177 ..Default::default()
178 },
179 }
180 }
181}
182
183#[derive(Debug)]
185pub struct SeismicAddOns<N: FullNodeComponents>
186where
187 N: FullNodeComponents,
188 SeismicEthApiBuilder: EthApiBuilder<N>,
189{
190 inner: RpcAddOns<
191 N, SeismicEthApiBuilder, SeismicEngineValidatorBuilder, >,
195}
196
197impl<N> SeismicAddOns<N>
198where
199 N: FullNodeComponents<
200 Types: NodeTypes<
201 ChainSpec = ChainSpec,
202 Primitives = SeismicPrimitives,
203 Storage = SeismicStorage,
204 Payload = SeismicEngineTypes,
205 >,
206 >,
207 SeismicEthApiBuilder: EthApiBuilder<N>,
208{
209 pub fn builder() -> SeismicAddOnsBuilder {
211 SeismicAddOnsBuilder::default()
212 }
213}
214
215#[derive(Debug, Default, Clone)]
217pub struct SeismicAddOnsBuilder {}
218
219impl SeismicAddOnsBuilder {
220 pub fn build<N>(self) -> SeismicAddOns<N>
222 where
223 N: FullNodeComponents<
224 Types: NodeTypes<
225 ChainSpec = ChainSpec,
226 Primitives = SeismicPrimitives,
227 Storage = SeismicStorage,
228 Payload = SeismicEngineTypes,
229 >,
230 Evm: ConfigureEvm<NextBlockEnvCtx = NextBlockEnvAttributes>,
231 >,
232 SeismicEthApiBuilder: EthApiBuilder<N>,
233 {
234 SeismicAddOns { inner: Default::default() }
235 }
236}
237
238impl<N: FullNodeComponents> Default for SeismicAddOns<N>
239where
240 N: FullNodeComponents<
241 Types: NodeTypes<
242 ChainSpec = ChainSpec,
243 Primitives = SeismicPrimitives,
244 Storage = SeismicStorage,
245 Payload = SeismicEngineTypes,
246 >,
247 Evm: ConfigureEvm<NextBlockEnvCtx = NextBlockEnvAttributes>,
248 >,
249 SeismicEthApiBuilder: EthApiBuilder<N>,
250{
251 fn default() -> Self {
252 Self::builder().build()
253 }
254}
255
256impl<N> NodeAddOns<N> for SeismicAddOns<N>
257where
258 N: FullNodeComponents<
259 Types: NodeTypes<
260 ChainSpec = ChainSpec,
261 Primitives = SeismicPrimitives,
262 Storage = SeismicStorage,
263 Payload = SeismicEngineTypes,
264 >,
265 Evm: ConfigureEvm<NextBlockEnvCtx = NextBlockEnvAttributes>,
266 >,
267 EthApiError: FromEvmError<N::Evm>,
268 EvmFactoryFor<N::Evm>: EvmFactory<Tx = seismic_revm::SeismicTransaction<TxEnv>>,
269{
270 type Handle = RpcHandle<N, SeismicEthApi<N>>;
271
272 async fn launch_add_ons(
273 self,
274 ctx: reth_node_api::AddOnsContext<'_, N>,
275 ) -> eyre::Result<Self::Handle> {
276 let validation_api = ValidationApi::new(
277 ctx.node.provider().clone(),
278 Arc::new(ctx.node.consensus().clone()),
279 ctx.node.evm_config().clone(),
280 ctx.config.rpc.flashbots_config(),
281 Box::new(ctx.node.task_executor().clone()),
282 Arc::new(SeismicEngineValidator::new(ctx.config.chain.clone())),
283 );
284
285 self.inner
286 .launch_add_ons_with(ctx, move |modules, _, _| {
287 modules.merge_if_module_configured(
288 RethRpcModule::Flashbots,
289 validation_api.into_rpc(),
290 )?;
291
292 Ok(())
293 })
294 .await
295 }
296}
297
298impl<N> RethRpcAddOns<N> for SeismicAddOns<N>
299where
300 N: FullNodeComponents<
301 Types: NodeTypes<
302 ChainSpec = ChainSpec,
303 Primitives = SeismicPrimitives,
304 Storage = SeismicStorage,
305 Payload = SeismicEngineTypes,
306 >,
307 Evm: ConfigureEvm<NextBlockEnvCtx = NextBlockEnvAttributes>,
308 >,
309 EthApiError: FromEvmError<N::Evm>,
310 EvmFactoryFor<N::Evm>: EvmFactory<Tx = seismic_revm::SeismicTransaction<TxEnv>>,
311 SeismicEthApi<N>: FullEthApiServer<Provider = N::Provider, Pool = N::Pool>, {
314 type EthApi = SeismicEthApi<N>;
315
316 fn hooks_mut(&mut self) -> &mut reth_node_builder::rpc::RpcHooks<N, Self::EthApi> {
317 self.inner.hooks_mut()
318 }
319}
320
321impl<N> EngineValidatorAddOn<N> for SeismicAddOns<N>
322where
323 N: FullNodeComponents<
324 Types: NodeTypes<
325 ChainSpec = ChainSpec,
326 Primitives = SeismicPrimitives,
327 Storage = SeismicStorage,
328 Payload = SeismicEngineTypes,
329 >,
330 Evm: ConfigureEvm<NextBlockEnvCtx = NextBlockEnvAttributes>,
331 >,
332 SeismicEthApi<N>: FullEthApiServer<Provider = N::Provider, Pool = N::Pool>, {
335 type Validator = SeismicEngineValidator;
336
337 async fn engine_validator(&self, ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::Validator> {
338 SeismicEngineValidatorBuilder::default().build(ctx).await
339 }
340}
341
342#[derive(Debug, Default, Clone, Copy)]
344#[non_exhaustive]
345pub struct SeismicExecutorBuilder;
346
347impl<Node> ExecutorBuilder<Node> for SeismicExecutorBuilder
348where
349 Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = SeismicPrimitives>>,
350{
351 type EVM = RealSeismicEvmConfig;
352
353 async fn build_evm(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::EVM> {
354 let evm_config = real_seismic_evm_config(ctx.chain_spec());
355
356 Ok(evm_config)
357 }
358}
359
360#[derive(Debug, Default, Clone, Copy)]
365#[non_exhaustive]
366pub struct SeismicPoolBuilder;
367
368impl<Node> PoolBuilder<Node> for SeismicPoolBuilder
369where
370 Node: FullNodeTypes<
371 Types: NodeTypes<
372 Payload = SeismicEngineTypes,
373 ChainSpec = ChainSpec,
374 Primitives = SeismicPrimitives,
375 >,
376 >,
377 {
381 type Pool = SeismicTransactionPool<Node::Provider, DiskFileBlobStore>;
382
383 async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {
384 let data_dir = ctx.config().datadir();
385 let pool_config = ctx.pool_config();
386
387 let blob_cache_size = if let Some(blob_cache_size) = pool_config.blob_cache_size {
388 blob_cache_size
389 } else {
390 let current_timestamp =
392 SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_secs();
393 let blob_params = ctx
394 .chain_spec()
395 .blob_params_at_timestamp(current_timestamp)
396 .unwrap_or(ctx.chain_spec().blob_params.cancun);
397
398 (blob_params.target_blob_count * EPOCH_SLOTS * 2) as u32
401 };
402
403 let custom_config =
404 DiskFileBlobStoreConfig::default().with_max_cached_entries(blob_cache_size);
405
406 let blob_store = DiskFileBlobStore::open(data_dir.blobstore(), custom_config)?;
407 let validator = TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone())
408 .with_head_timestamp(ctx.head().timestamp)
409 .kzg_settings(ctx.kzg_settings()?)
410 .with_local_transactions_config(pool_config.local_transactions_config.clone())
411 .with_additional_tasks(ctx.config().txpool.additional_validation_tasks)
412 .build_with_tasks(ctx.task_executor().clone(), blob_store.clone());
413
414 let transaction_pool = reth_transaction_pool::Pool::new(
415 validator,
416 CoinbaseTipOrdering::default(),
417 blob_store,
418 pool_config,
419 );
420 let transactions_path = data_dir.txpool_transactions();
422
423 {
425 let pool = transaction_pool.clone();
426 let chain_events = ctx.provider().canonical_state_stream();
427 let client = ctx.provider().clone();
428 let transactions_backup_config =
429
430reth_transaction_pool::maintain::LocalTransactionBackupConfig::with_local_txs_backup(transactions_path);
431
432 ctx.task_executor().spawn_critical_with_graceful_shutdown_signal(
433 "local transactions backup task",
434 |shutdown| {
435 reth_transaction_pool::maintain::backup_local_transactions_task(
436 shutdown,
437 pool.clone(),
438 transactions_backup_config,
439 )
440 },
441 );
442
443 ctx.task_executor().spawn_critical(
445 "txpool maintenance task",
446 reth_transaction_pool::maintain::maintain_transaction_pool_future(
447 client,
448 pool,
449 chain_events,
450 ctx.task_executor().clone(),
451 reth_transaction_pool::maintain::MaintainPoolConfig {
452 max_tx_lifetime: transaction_pool.config().max_queued_lifetime,
453 ..Default::default()
454 },
455 ),
456 );
457 }
459
460 Ok(transaction_pool)
461 }
462}
463
464#[derive(Debug, Default, Clone)]
466pub struct SeismicPayloadBuilder;
467
468impl SeismicPayloadBuilder {
469 pub fn build<Types, Node, Evm, Pool>(
472 self,
473 evm_config: Evm,
474 ctx: &BuilderContext<Node>,
475 pool: Pool,
476 ) -> eyre::Result<reth_seismic_payload_builder::SeismicPayloadBuilder<Pool, Node::Provider, Evm>>
477 where
478 Node: FullNodeTypes<
479 Types: NodeTypes<
480 Payload = SeismicEngineTypes,
481 ChainSpec = ChainSpec,
482 Primitives = SeismicPrimitives,
483 >,
484 >,
485 Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
486 + Unpin
487 + 'static,
488 Evm: ConfigureEvm<Primitives = PrimitivesTy<Node::Types>>,
489 {
491 let conf = ctx.payload_builder_config();
492 let chain = ctx.chain_spec().chain();
493 let gas_limit = conf.gas_limit_for(chain);
494
495 Ok(reth_seismic_payload_builder::SeismicPayloadBuilder::new(
496 ctx.provider().clone(),
497 pool,
498 evm_config,
499 SeismicBuilderConfig::new().with_gas_limit(gas_limit),
500 ))
501 }
502}
503
504impl<Node, Pool, CB> PayloadBuilderBuilder<Node, Pool, SeismicEvmConfig<CB>>
505 for SeismicPayloadBuilder
506where
507 Node: FullNodeTypes<
508 Types: NodeTypes<
509 Payload = SeismicEngineTypes,
510 ChainSpec = ChainSpec,
511 Primitives = SeismicPrimitives,
512 >,
513 >,
514 Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
515 + Unpin
516 + 'static,
517
518 CB: SyncEnclaveApiClientBuilder + 'static,
519{
520 type PayloadBuilder = reth_seismic_payload_builder::SeismicPayloadBuilder<
521 Pool,
522 Node::Provider,
523 SeismicEvmConfig<CB>,
524 >;
525
526 async fn build_payload_builder(
527 self,
528 ctx: &BuilderContext<Node>,
529 pool: Pool,
530 evm_config: SeismicEvmConfig<CB>,
531 ) -> eyre::Result<Self::PayloadBuilder> {
532 let conf = ctx.payload_builder_config();
533 let chain = ctx.chain_spec().chain();
534 let gas_limit = conf.gas_limit_for(chain);
535
536 let payload_builder = reth_seismic_payload_builder::SeismicPayloadBuilder::new(
537 ctx.provider().clone(),
538 pool,
539 evm_config,
540 SeismicBuilderConfig::new().with_gas_limit(gas_limit),
541 );
542 Ok(payload_builder)
543 }
544}
545
546#[derive(Debug, Default, Clone, Copy)]
548pub struct SeismicNetworkBuilder {
549 }
551
552impl<Node, Pool> NetworkBuilder<Node, Pool> for SeismicNetworkBuilder
553where
554 Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = SeismicPrimitives>>,
555 Pool: TransactionPool<
556 Transaction: PoolTransaction<Consensus = TxTy<Node::Types>, Pooled = SeismicTxEnvelope>, > + Unpin
558 + 'static,
559{
560 type Network = NetworkHandle<SeismicNetworkPrimitives>;
561
562 async fn build_network(
563 self,
564 ctx: &BuilderContext<Node>,
565 pool: Pool,
566 ) -> eyre::Result<NetworkHandle<SeismicNetworkPrimitives>> {
567 let network = ctx.network_builder().await?;
568 let handle = ctx.start_network(network, pool);
569 Ok(handle)
572 }
573}
574
575#[derive(Debug, Default, Clone)]
577#[non_exhaustive]
578pub struct SeismicConsensusBuilder;
579
580impl<Node> ConsensusBuilder<Node> for SeismicConsensusBuilder
581where
582 Node: FullNodeTypes<Types: NodeTypes<ChainSpec = ChainSpec, Primitives = SeismicPrimitives>>,
583{
584 type Consensus = Arc<dyn FullConsensus<SeismicPrimitives, Error = ConsensusError>>;
585
586 async fn build_consensus(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Consensus> {
587 Ok(Arc::new(EthBeaconConsensus::new(ctx.chain_spec())))
588 }
589}
590
591#[derive(Debug, Default, Clone)]
593#[non_exhaustive]
594pub struct SeismicEngineValidatorBuilder;
595
596impl<Node, Types> EngineValidatorBuilder<Node> for SeismicEngineValidatorBuilder
597where
598 Types: NodeTypes<
599 ChainSpec = ChainSpec,
600 Primitives = SeismicPrimitives,
601 Payload = SeismicEngineTypes,
602 >,
603 Node: FullNodeComponents<Types = Types>,
604{
605 type Validator = SeismicEngineValidator;
606
607 async fn build(self, ctx: &AddOnsContext<'_, Node>) -> eyre::Result<Self::Validator> {
608 Ok(SeismicEngineValidator::new(ctx.config.chain.clone()))
609 }
610}
611#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
613#[non_exhaustive]
614pub struct SeismicNetworkPrimitives;
615
616impl NetworkPrimitives for SeismicNetworkPrimitives {
617 type BlockHeader = alloy_consensus::Header;
618 type BlockBody = alloy_consensus::BlockBody<SeismicTransactionSigned>;
619 type Block = alloy_consensus::Block<SeismicTransactionSigned>;
620 type BroadcastedTransaction = SeismicTransactionSigned;
621 type PooledTransaction = SeismicTxEnvelope;
622 type Receipt = SeismicReceipt;
623}