1use crate::{
4 args::RollupArgs,
5 engine::OpEngineValidator,
6 txpool::{OpTransactionPool, OpTransactionValidator},
7 OpEngineApiBuilder, OpEngineTypes,
8};
9use op_alloy_consensus::OpPooledTransaction;
10use reth_chainspec::{EthChainSpec, Hardforks};
11use reth_evm::{execute::BasicBlockExecutorProvider, ConfigureEvm, EvmFactory, EvmFactoryFor};
12use reth_network::{NetworkConfig, NetworkHandle, NetworkManager, NetworkPrimitives, PeersInfo};
13use reth_node_api::{
14 AddOnsContext, FullNodeComponents, KeyHasherTy, NodeAddOns, NodePrimitives, PrimitivesTy, TxTy,
15};
16use reth_node_builder::{
17 components::{
18 BasicPayloadServiceBuilder, ComponentsBuilder, ConsensusBuilder, ExecutorBuilder,
19 NetworkBuilder, PayloadBuilderBuilder, PoolBuilder, PoolBuilderConfigOverrides,
20 },
21 node::{FullNodeTypes, NodeTypes, NodeTypesWithEngine},
22 rpc::{
23 EngineValidatorAddOn, EngineValidatorBuilder, EthApiBuilder, RethRpcAddOns, RpcAddOns,
24 RpcHandle,
25 },
26 BuilderContext, DebugNode, Node, NodeAdapter, NodeComponentsBuilder,
27};
28use reth_optimism_chainspec::OpChainSpec;
29use reth_optimism_consensus::OpBeaconConsensus;
30use reth_optimism_evm::{OpEvmConfig, OpNextBlockEnvAttributes};
31use reth_optimism_forks::OpHardforks;
32use reth_optimism_payload_builder::{
33 builder::OpPayloadTransactions,
34 config::{OpBuilderConfig, OpDAConfig},
35};
36use reth_optimism_primitives::{DepositReceipt, OpPrimitives, OpReceipt, OpTransactionSigned};
37use reth_optimism_rpc::{
38 eth::{ext::OpEthExtApi, OpEthApiBuilder},
39 miner::{MinerApiExtServer, OpMinerExtApi},
40 witness::{DebugExecutionWitnessApiServer, OpDebugWitnessApi},
41 OpEthApi, OpEthApiError, SequencerClient,
42};
43use reth_optimism_txpool::{conditional::MaybeConditionalTransaction, OpPooledTx};
44use reth_provider::{providers::ProviderFactoryBuilder, CanonStateSubscriptions, EthStorage};
45use reth_rpc_eth_api::ext::L2EthApiExtServer;
46use reth_rpc_eth_types::error::FromEvmError;
47use reth_rpc_server_types::RethRpcModule;
48use reth_tracing::tracing::{debug, info};
49use reth_transaction_pool::{
50 blobstore::DiskFileBlobStore, CoinbaseTipOrdering, EthPoolTransaction, PoolTransaction,
51 TransactionPool, TransactionValidationTaskExecutor,
52};
53use reth_trie_db::MerklePatriciaTrie;
54use revm::context::TxEnv;
55use std::sync::Arc;
56
57pub type OpStorage = EthStorage<OpTransactionSigned>;
59
60#[derive(Debug, Default, Clone)]
62#[non_exhaustive]
63pub struct OpNode {
64 pub args: RollupArgs,
66 pub da_config: OpDAConfig,
73}
74
75impl OpNode {
76 pub fn new(args: RollupArgs) -> Self {
78 Self { args, da_config: OpDAConfig::default() }
79 }
80
81 pub fn with_da_config(mut self, da_config: OpDAConfig) -> Self {
83 self.da_config = da_config;
84 self
85 }
86
87 pub fn components<Node>(
89 &self,
90 ) -> ComponentsBuilder<
91 Node,
92 OpPoolBuilder,
93 BasicPayloadServiceBuilder<OpPayloadBuilder>,
94 OpNetworkBuilder,
95 OpExecutorBuilder,
96 OpConsensusBuilder,
97 >
98 where
99 Node: FullNodeTypes<
100 Types: NodeTypesWithEngine<
101 Engine = OpEngineTypes,
102 ChainSpec = OpChainSpec,
103 Primitives = OpPrimitives,
104 >,
105 >,
106 {
107 let RollupArgs { disable_txpool_gossip, compute_pending_block, discovery_v4, .. } =
108 self.args;
109 ComponentsBuilder::default()
110 .node_types::<Node>()
111 .pool(
112 OpPoolBuilder::default()
113 .with_enable_tx_conditional(self.args.enable_tx_conditional),
114 )
115 .payload(BasicPayloadServiceBuilder::new(
116 OpPayloadBuilder::new(compute_pending_block).with_da_config(self.da_config.clone()),
117 ))
118 .network(OpNetworkBuilder {
119 disable_txpool_gossip,
120 disable_discovery_v4: !discovery_v4,
121 })
122 .executor(OpExecutorBuilder::default())
123 .consensus(OpConsensusBuilder::default())
124 }
125
126 pub fn provider_factory_builder() -> ProviderFactoryBuilder<Self> {
157 ProviderFactoryBuilder::default()
158 }
159}
160
161impl<N> Node<N> for OpNode
162where
163 N: FullNodeTypes<
164 Types: NodeTypesWithEngine<
165 Engine = OpEngineTypes,
166 ChainSpec = OpChainSpec,
167 Primitives = OpPrimitives,
168 Storage = OpStorage,
169 >,
170 >,
171{
172 type ComponentsBuilder = ComponentsBuilder<
173 N,
174 OpPoolBuilder,
175 BasicPayloadServiceBuilder<OpPayloadBuilder>,
176 OpNetworkBuilder,
177 OpExecutorBuilder,
178 OpConsensusBuilder,
179 >;
180
181 type AddOns =
182 OpAddOns<NodeAdapter<N, <Self::ComponentsBuilder as NodeComponentsBuilder<N>>::Components>>;
183
184 fn components_builder(&self) -> Self::ComponentsBuilder {
185 Self::components(self)
186 }
187
188 fn add_ons(&self) -> Self::AddOns {
189 Self::AddOns::builder()
190 .with_sequencer(self.args.sequencer_http.clone())
191 .with_da_config(self.da_config.clone())
192 .with_enable_tx_conditional(self.args.enable_tx_conditional)
193 .build()
194 }
195}
196
197impl<N> DebugNode<N> for OpNode
198where
199 N: FullNodeComponents<Types = Self>,
200{
201 type RpcBlock = alloy_rpc_types_eth::Block<op_alloy_consensus::OpTxEnvelope>;
202
203 fn rpc_to_primitive_block(rpc_block: Self::RpcBlock) -> reth_node_api::BlockTy<Self> {
204 let alloy_rpc_types_eth::Block { header, transactions, .. } = rpc_block;
205 reth_optimism_primitives::OpBlock {
206 header: header.inner,
207 body: reth_optimism_primitives::OpBlockBody {
208 transactions: transactions.into_transactions().map(Into::into).collect(),
209 ..Default::default()
210 },
211 }
212 }
213}
214
215impl NodeTypes for OpNode {
216 type Primitives = OpPrimitives;
217 type ChainSpec = OpChainSpec;
218 type StateCommitment = MerklePatriciaTrie;
219 type Storage = OpStorage;
220}
221
222impl NodeTypesWithEngine for OpNode {
223 type Engine = OpEngineTypes;
224}
225
226#[derive(Debug)]
228pub struct OpAddOns<N>
229where
230 N: FullNodeComponents,
231 OpEthApiBuilder: EthApiBuilder<N>,
232{
233 pub rpc_add_ons: RpcAddOns<
236 N,
237 OpEthApiBuilder,
238 OpEngineValidatorBuilder,
239 OpEngineApiBuilder<OpEngineValidatorBuilder>,
240 >,
241 pub da_config: OpDAConfig,
243 pub sequencer_client: Option<SequencerClient>,
246 enable_tx_conditional: bool,
248}
249
250impl<N> Default for OpAddOns<N>
251where
252 N: FullNodeComponents<Types: NodeTypes<Primitives = OpPrimitives>>,
253 OpEthApiBuilder: EthApiBuilder<N>,
254{
255 fn default() -> Self {
256 Self::builder().build()
257 }
258}
259
260impl<N> OpAddOns<N>
261where
262 N: FullNodeComponents<Types: NodeTypes<Primitives = OpPrimitives>>,
263 OpEthApiBuilder: EthApiBuilder<N>,
264{
265 pub fn builder() -> OpAddOnsBuilder {
267 OpAddOnsBuilder::default()
268 }
269}
270
271impl<N> NodeAddOns<N> for OpAddOns<N>
272where
273 N: FullNodeComponents<
274 Types: NodeTypesWithEngine<
275 ChainSpec = OpChainSpec,
276 Primitives = OpPrimitives,
277 Storage = OpStorage,
278 Engine = OpEngineTypes,
279 >,
280 Evm: ConfigureEvm<NextBlockEnvCtx = OpNextBlockEnvAttributes>,
281 >,
282 OpEthApiError: FromEvmError<N::Evm>,
283 <N::Pool as TransactionPool>::Transaction: OpPooledTx,
284 EvmFactoryFor<N::Evm>: EvmFactory<Tx = op_revm::OpTransaction<TxEnv>>,
285{
286 type Handle = RpcHandle<N, OpEthApi<N>>;
287
288 async fn launch_add_ons(
289 self,
290 ctx: reth_node_api::AddOnsContext<'_, N>,
291 ) -> eyre::Result<Self::Handle> {
292 let Self { rpc_add_ons, da_config, sequencer_client, enable_tx_conditional } = self;
293
294 let builder = reth_optimism_payload_builder::OpPayloadBuilder::new(
295 ctx.node.pool().clone(),
296 ctx.node.provider().clone(),
297 ctx.node.evm_config().clone(),
298 );
299 let debug_ext = OpDebugWitnessApi::new(
301 ctx.node.provider().clone(),
302 Box::new(ctx.node.task_executor().clone()),
303 builder,
304 );
305 let miner_ext = OpMinerExtApi::new(da_config);
306
307 let tx_conditional_ext: OpEthExtApi<N::Pool, N::Provider> = OpEthExtApi::new(
308 sequencer_client,
309 ctx.node.pool().clone(),
310 ctx.node.provider().clone(),
311 );
312 rpc_add_ons
313 .launch_add_ons_with(ctx, move |modules, auth_modules| {
314 debug!(target: "reth::cli", "Installing debug payload witness rpc endpoint");
315 modules.merge_if_module_configured(RethRpcModule::Debug, debug_ext.into_rpc())?;
316
317 modules.merge_if_module_configured(
319 RethRpcModule::Miner,
320 miner_ext.clone().into_rpc(),
321 )?;
322
323 if modules.module_config().contains_any(&RethRpcModule::Miner) {
325 debug!(target: "reth::cli", "Installing miner DA rpc enddpoint");
326 auth_modules.merge_auth_methods(miner_ext.into_rpc())?;
327 }
328
329 if enable_tx_conditional {
330 modules.merge_if_module_configured(
332 RethRpcModule::Eth,
333 tx_conditional_ext.into_rpc(),
334 )?;
335 }
336
337 Ok(())
338 })
339 .await
340 }
341}
342
343impl<N> RethRpcAddOns<N> for OpAddOns<N>
344where
345 N: FullNodeComponents<
346 Types: NodeTypesWithEngine<
347 ChainSpec = OpChainSpec,
348 Primitives = OpPrimitives,
349 Storage = OpStorage,
350 Engine = OpEngineTypes,
351 >,
352 Evm: ConfigureEvm<NextBlockEnvCtx = OpNextBlockEnvAttributes>,
353 >,
354 OpEthApiError: FromEvmError<N::Evm>,
355 <<N as FullNodeComponents>::Pool as TransactionPool>::Transaction: OpPooledTx,
356 EvmFactoryFor<N::Evm>: EvmFactory<Tx = op_revm::OpTransaction<TxEnv>>,
357{
358 type EthApi = OpEthApi<N>;
359
360 fn hooks_mut(&mut self) -> &mut reth_node_builder::rpc::RpcHooks<N, Self::EthApi> {
361 self.rpc_add_ons.hooks_mut()
362 }
363}
364
365impl<N> EngineValidatorAddOn<N> for OpAddOns<N>
366where
367 N: FullNodeComponents<
368 Types: NodeTypesWithEngine<
369 ChainSpec = OpChainSpec,
370 Primitives = OpPrimitives,
371 Engine = OpEngineTypes,
372 >,
373 >,
374 OpEthApiBuilder: EthApiBuilder<N>,
375{
376 type Validator = OpEngineValidator<N::Provider>;
377
378 async fn engine_validator(&self, ctx: &AddOnsContext<'_, N>) -> eyre::Result<Self::Validator> {
379 OpEngineValidatorBuilder::default().build(ctx).await
380 }
381}
382
383#[derive(Debug, Default, Clone)]
385#[non_exhaustive]
386pub struct OpAddOnsBuilder {
387 sequencer_client: Option<SequencerClient>,
390 da_config: Option<OpDAConfig>,
392 enable_tx_conditional: bool,
394}
395
396impl OpAddOnsBuilder {
397 pub fn with_sequencer(mut self, sequencer_client: Option<String>) -> Self {
399 self.sequencer_client = sequencer_client.map(SequencerClient::new);
400 self
401 }
402
403 pub fn with_da_config(mut self, da_config: OpDAConfig) -> Self {
405 self.da_config = Some(da_config);
406 self
407 }
408
409 pub fn with_enable_tx_conditional(mut self, enable_tx_conditional: bool) -> Self {
411 self.enable_tx_conditional = enable_tx_conditional;
412 self
413 }
414}
415
416impl OpAddOnsBuilder {
417 pub fn build<N>(self) -> OpAddOns<N>
419 where
420 N: FullNodeComponents<Types: NodeTypes<Primitives = OpPrimitives>>,
421 OpEthApiBuilder: EthApiBuilder<N>,
422 {
423 let Self { sequencer_client, da_config, enable_tx_conditional } = self;
424
425 let sequencer_client_clone = sequencer_client.clone();
426 OpAddOns {
427 rpc_add_ons: RpcAddOns::new(
428 OpEthApiBuilder::default().with_sequencer(sequencer_client_clone),
429 Default::default(),
430 Default::default(),
431 ),
432 da_config: da_config.unwrap_or_default(),
433 sequencer_client,
434 enable_tx_conditional,
435 }
436 }
437}
438
439#[derive(Debug, Default, Clone, Copy)]
441#[non_exhaustive]
442pub struct OpExecutorBuilder;
443
444impl<Node> ExecutorBuilder<Node> for OpExecutorBuilder
445where
446 Node: FullNodeTypes<Types: NodeTypes<ChainSpec = OpChainSpec, Primitives = OpPrimitives>>,
447{
448 type EVM = OpEvmConfig;
449 type Executor = BasicBlockExecutorProvider<Self::EVM>;
450
451 async fn build_evm(
452 self,
453 ctx: &BuilderContext<Node>,
454 ) -> eyre::Result<(Self::EVM, Self::Executor)> {
455 let evm_config = OpEvmConfig::optimism(ctx.chain_spec());
456 let executor = BasicBlockExecutorProvider::new(evm_config.clone());
457
458 Ok((evm_config, executor))
459 }
460}
461
462#[derive(Debug, Clone)]
467pub struct OpPoolBuilder<T = crate::txpool::OpPooledTransaction> {
468 pub pool_config_overrides: PoolBuilderConfigOverrides,
470 pub enable_tx_conditional: bool,
472 _pd: core::marker::PhantomData<T>,
474}
475
476impl<T> Default for OpPoolBuilder<T> {
477 fn default() -> Self {
478 Self {
479 pool_config_overrides: Default::default(),
480 enable_tx_conditional: false,
481 _pd: Default::default(),
482 }
483 }
484}
485
486impl<T> OpPoolBuilder<T> {
487 pub fn with_enable_tx_conditional(mut self, enable_tx_conditional: bool) -> Self {
489 self.enable_tx_conditional = enable_tx_conditional;
490 self
491 }
492
493 pub fn with_pool_config_overrides(
495 mut self,
496 pool_config_overrides: PoolBuilderConfigOverrides,
497 ) -> Self {
498 self.pool_config_overrides = pool_config_overrides;
499 self
500 }
501}
502
503impl<Node, T> PoolBuilder<Node> for OpPoolBuilder<T>
504where
505 Node: FullNodeTypes<Types: NodeTypes<ChainSpec: OpHardforks>>,
506 T: EthPoolTransaction<Consensus = TxTy<Node::Types>> + MaybeConditionalTransaction,
507{
508 type Pool = OpTransactionPool<Node::Provider, DiskFileBlobStore, T>;
509
510 async fn build_pool(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Pool> {
511 let Self { pool_config_overrides, .. } = self;
512 let data_dir = ctx.config().datadir();
513 let blob_store = DiskFileBlobStore::open(data_dir.blobstore(), Default::default())?;
514
515 let validator = TransactionValidationTaskExecutor::eth_builder(ctx.provider().clone())
516 .no_eip4844()
517 .with_head_timestamp(ctx.head().timestamp)
518 .kzg_settings(ctx.kzg_settings()?)
519 .with_additional_tasks(
520 pool_config_overrides
521 .additional_validation_tasks
522 .unwrap_or_else(|| ctx.config().txpool.additional_validation_tasks),
523 )
524 .build_with_tasks(ctx.task_executor().clone(), blob_store.clone())
525 .map(|validator| {
526 OpTransactionValidator::new(validator)
527 .require_l1_data_gas_fee(!ctx.config().dev.dev)
530 });
531
532 let transaction_pool = reth_transaction_pool::Pool::new(
533 validator,
534 CoinbaseTipOrdering::default(),
535 blob_store,
536 pool_config_overrides.apply(ctx.pool_config()),
537 );
538 info!(target: "reth::cli", "Transaction pool initialized");
539 let transactions_path = data_dir.txpool_transactions();
540
541 {
543 let pool = transaction_pool.clone();
544 let chain_events = ctx.provider().canonical_state_stream();
545 let client = ctx.provider().clone();
546 let transactions_backup_config =
547 reth_transaction_pool::maintain::LocalTransactionBackupConfig::with_local_txs_backup(transactions_path);
548
549 ctx.task_executor().spawn_critical_with_graceful_shutdown_signal(
550 "local transactions backup task",
551 |shutdown| {
552 reth_transaction_pool::maintain::backup_local_transactions_task(
553 shutdown,
554 pool.clone(),
555 transactions_backup_config,
556 )
557 },
558 );
559
560 ctx.task_executor().spawn_critical(
562 "txpool maintenance task",
563 reth_transaction_pool::maintain::maintain_transaction_pool_future(
564 client,
565 pool.clone(),
566 chain_events,
567 ctx.task_executor().clone(),
568 reth_transaction_pool::maintain::MaintainPoolConfig {
569 max_tx_lifetime: pool.config().max_queued_lifetime,
570 ..Default::default()
571 },
572 ),
573 );
574 debug!(target: "reth::cli", "Spawned txpool maintenance task");
575
576 if self.enable_tx_conditional {
577 let chain_events = ctx.provider().canonical_state_stream();
579 ctx.task_executor().spawn_critical(
580 "Op txpool maintenance task",
581 reth_optimism_txpool::maintain::maintain_transaction_pool_future(
582 pool,
583 chain_events,
584 ),
585 );
586 debug!(target: "reth::cli", "Spawned Op txpool maintenance task");
587 }
588 }
589
590 Ok(transaction_pool)
591 }
592}
593
594#[derive(Debug, Default, Clone)]
596pub struct OpPayloadBuilder<Txs = ()> {
597 pub compute_pending_block: bool,
606 pub best_transactions: Txs,
609 pub da_config: OpDAConfig,
612}
613
614impl OpPayloadBuilder {
615 pub fn new(compute_pending_block: bool) -> Self {
618 Self { compute_pending_block, best_transactions: (), da_config: OpDAConfig::default() }
619 }
620
621 pub fn with_da_config(mut self, da_config: OpDAConfig) -> Self {
623 self.da_config = da_config;
624 self
625 }
626}
627
628impl<Txs> OpPayloadBuilder<Txs> {
629 pub fn with_transactions<T>(self, best_transactions: T) -> OpPayloadBuilder<T> {
632 let Self { compute_pending_block, da_config, .. } = self;
633 OpPayloadBuilder { compute_pending_block, best_transactions, da_config }
634 }
635
636 pub fn build<Node, Evm, Pool>(
639 self,
640 evm_config: Evm,
641 ctx: &BuilderContext<Node>,
642 pool: Pool,
643 ) -> eyre::Result<reth_optimism_payload_builder::OpPayloadBuilder<Pool, Node::Provider, Evm, Txs>>
644 where
645 Node: FullNodeTypes<
646 Types: NodeTypesWithEngine<
647 Engine = OpEngineTypes,
648 ChainSpec = OpChainSpec,
649 Primitives = OpPrimitives,
650 >,
651 >,
652 Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
653 + Unpin
654 + 'static,
655 Evm: ConfigureEvm<Primitives = PrimitivesTy<Node::Types>>,
656 Txs: OpPayloadTransactions<Pool::Transaction>,
657 {
658 let payload_builder = reth_optimism_payload_builder::OpPayloadBuilder::with_builder_config(
659 pool,
660 ctx.provider().clone(),
661 evm_config,
662 OpBuilderConfig { da_config: self.da_config.clone() },
663 )
664 .with_transactions(self.best_transactions.clone())
665 .set_compute_pending_block(self.compute_pending_block);
666 Ok(payload_builder)
667 }
668}
669
670impl<Node, Pool, Txs> PayloadBuilderBuilder<Node, Pool> for OpPayloadBuilder<Txs>
671where
672 Node: FullNodeTypes<
673 Types: NodeTypesWithEngine<
674 Engine = OpEngineTypes,
675 ChainSpec = OpChainSpec,
676 Primitives = OpPrimitives,
677 >,
678 >,
679 Pool: TransactionPool<Transaction: PoolTransaction<Consensus = TxTy<Node::Types>>>
680 + Unpin
681 + 'static,
682 Txs: OpPayloadTransactions<Pool::Transaction>,
683 <Pool as TransactionPool>::Transaction: OpPooledTx,
684{
685 type PayloadBuilder =
686 reth_optimism_payload_builder::OpPayloadBuilder<Pool, Node::Provider, OpEvmConfig, Txs>;
687
688 async fn build_payload_builder(
689 self,
690 ctx: &BuilderContext<Node>,
691 pool: Pool,
692 ) -> eyre::Result<Self::PayloadBuilder> {
693 self.build(OpEvmConfig::optimism(ctx.chain_spec()), ctx, pool)
694 }
695}
696
697#[derive(Debug, Default, Clone)]
699pub struct OpNetworkBuilder {
700 pub disable_txpool_gossip: bool,
702 pub disable_discovery_v4: bool,
704}
705
706impl OpNetworkBuilder {
707 pub fn network_config<Node>(
711 &self,
712 ctx: &BuilderContext<Node>,
713 ) -> eyre::Result<NetworkConfig<<Node as FullNodeTypes>::Provider, OpNetworkPrimitives>>
714 where
715 Node: FullNodeTypes<Types: NodeTypes<ChainSpec: Hardforks>>,
716 {
717 let Self { disable_txpool_gossip, disable_discovery_v4 } = self.clone();
718 let args = &ctx.config().network;
719 let network_builder = ctx
720 .network_config_builder()?
721 .apply(|mut builder| {
723 let rlpx_socket = (args.addr, args.port).into();
724 if disable_discovery_v4 || args.discovery.disable_discovery {
725 builder = builder.disable_discv4_discovery();
726 }
727 if !args.discovery.disable_discovery {
728 builder = builder.discovery_v5(
729 args.discovery.discovery_v5_builder(
730 rlpx_socket,
731 ctx.config()
732 .network
733 .resolved_bootnodes()
734 .or_else(|| ctx.chain_spec().bootnodes())
735 .unwrap_or_default(),
736 ),
737 );
738 }
739
740 builder
741 });
742
743 let mut network_config = ctx.build_network_config(network_builder);
744
745 network_config.tx_gossip_disabled = disable_txpool_gossip;
749
750 Ok(network_config)
751 }
752}
753
754impl<Node, Pool> NetworkBuilder<Node, Pool> for OpNetworkBuilder
755where
756 Node: FullNodeTypes<Types: NodeTypes<ChainSpec = OpChainSpec, Primitives = OpPrimitives>>,
757 Pool: TransactionPool<
758 Transaction: PoolTransaction<
759 Consensus = TxTy<Node::Types>,
760 Pooled = OpPooledTransaction,
761 >,
762 > + Unpin
763 + 'static,
764{
765 type Primitives = OpNetworkPrimitives;
766
767 async fn build_network(
768 self,
769 ctx: &BuilderContext<Node>,
770 pool: Pool,
771 ) -> eyre::Result<NetworkHandle<Self::Primitives>> {
772 let network_config = self.network_config(ctx)?;
773 let network = NetworkManager::builder(network_config).await?;
774 let handle = ctx.start_network(network, pool);
775 info!(target: "reth::cli", enode=%handle.local_node_record(), "P2P networking initialized");
776
777 Ok(handle)
778 }
779}
780
781#[derive(Debug, Default, Clone)]
783#[non_exhaustive]
784pub struct OpConsensusBuilder;
785
786impl<Node> ConsensusBuilder<Node> for OpConsensusBuilder
787where
788 Node: FullNodeTypes<
789 Types: NodeTypes<
790 ChainSpec: OpHardforks,
791 Primitives: NodePrimitives<Receipt: DepositReceipt>,
792 >,
793 >,
794{
795 type Consensus = Arc<OpBeaconConsensus<<Node::Types as NodeTypes>::ChainSpec>>;
796
797 async fn build_consensus(self, ctx: &BuilderContext<Node>) -> eyre::Result<Self::Consensus> {
798 Ok(Arc::new(OpBeaconConsensus::new(ctx.chain_spec())))
799 }
800}
801
802#[derive(Debug, Default, Clone)]
804#[non_exhaustive]
805pub struct OpEngineValidatorBuilder;
806
807impl<Node, Types> EngineValidatorBuilder<Node> for OpEngineValidatorBuilder
808where
809 Types: NodeTypesWithEngine<
810 ChainSpec = OpChainSpec,
811 Primitives = OpPrimitives,
812 Engine = OpEngineTypes,
813 >,
814 Node: FullNodeComponents<Types = Types>,
815{
816 type Validator = OpEngineValidator<Node::Provider>;
817
818 async fn build(self, ctx: &AddOnsContext<'_, Node>) -> eyre::Result<Self::Validator> {
819 Ok(OpEngineValidator::new::<KeyHasherTy<Types>>(
820 ctx.config.chain.clone(),
821 ctx.node.provider().clone(),
822 ))
823 }
824}
825
826#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
828#[non_exhaustive]
829pub struct OpNetworkPrimitives;
830
831impl NetworkPrimitives for OpNetworkPrimitives {
832 type BlockHeader = alloy_consensus::Header;
833 type BlockBody = reth_primitives::BlockBody<OpTransactionSigned>;
834 type Block = reth_primitives::Block<OpTransactionSigned>;
835 type BroadcastedTransaction = OpTransactionSigned;
836 type PooledTransaction = OpPooledTransaction;
837 type Receipt = OpReceipt;
838}