1use crate::{ChainSpec, DepositContract};
2use alloc::{boxed::Box, vec::Vec};
3use alloy_chains::Chain;
4use alloy_eips::{eip1559::BaseFeeParams, eip7840::BlobParams};
5use alloy_genesis::Genesis;
6use alloy_primitives::{B256, U256};
7use core::fmt::{Debug, Display};
8use reth_ethereum_forks::EthereumHardforks;
9use reth_network_peers::NodeRecord;
10use reth_primitives_traits::{AlloyBlockHeader, BlockHeader};
11
12#[auto_impl::auto_impl(&, Arc)]
14pub trait EthChainSpec: Send + Sync + Unpin + Debug {
15 type Header: BlockHeader;
17
18 fn chain(&self) -> Chain;
20
21 fn chain_id(&self) -> u64 {
23 self.chain().id()
24 }
25
26 fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams;
28
29 fn blob_params_at_timestamp(&self, timestamp: u64) -> Option<BlobParams>;
31
32 fn deposit_contract(&self) -> Option<&DepositContract>;
34
35 fn genesis_hash(&self) -> B256;
37
38 fn prune_delete_limit(&self) -> usize;
40
41 fn display_hardforks(&self) -> Box<dyn Display>;
43
44 fn genesis_header(&self) -> &Self::Header;
46
47 fn genesis(&self) -> &Genesis;
49
50 fn bootnodes(&self) -> Option<Vec<NodeRecord>>;
52
53 fn is_optimism(&self) -> bool {
55 self.chain().is_optimism()
56 }
57
58 fn is_ethereum(&self) -> bool {
60 self.chain().is_ethereum()
61 }
62
63 fn final_paris_total_difficulty(&self) -> Option<U256>;
65
66 fn next_block_base_fee(&self, parent: &Self::Header, target_timestamp: u64) -> Option<u64> {
68 parent.next_block_base_fee(self.base_fee_params_at_timestamp(target_timestamp))
69 }
70}
71
72impl<H: BlockHeader> EthChainSpec for ChainSpec<H> {
73 type Header = H;
74
75 fn chain(&self) -> Chain {
76 self.chain
77 }
78
79 fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams {
80 self.base_fee_params_at_timestamp(timestamp)
81 }
82
83 fn blob_params_at_timestamp(&self, timestamp: u64) -> Option<BlobParams> {
84 if let Some(blob_param) = self.blob_params.active_scheduled_params_at_timestamp(timestamp) {
85 Some(*blob_param)
86 } else if self.is_osaka_active_at_timestamp(timestamp) {
87 Some(self.blob_params.osaka)
88 } else if self.is_prague_active_at_timestamp(timestamp) {
89 Some(self.blob_params.prague)
90 } else if self.is_cancun_active_at_timestamp(timestamp) {
91 Some(self.blob_params.cancun)
92 } else {
93 None
94 }
95 }
96
97 fn deposit_contract(&self) -> Option<&DepositContract> {
98 self.deposit_contract.as_ref()
99 }
100
101 fn genesis_hash(&self) -> B256 {
102 self.genesis_hash()
103 }
104
105 fn prune_delete_limit(&self) -> usize {
106 self.prune_delete_limit
107 }
108
109 fn display_hardforks(&self) -> Box<dyn Display> {
110 Box::new(Self::display_hardforks(self))
111 }
112
113 fn genesis_header(&self) -> &Self::Header {
114 self.genesis_header()
115 }
116
117 fn genesis(&self) -> &Genesis {
118 self.genesis()
119 }
120
121 fn bootnodes(&self) -> Option<Vec<NodeRecord>> {
122 self.bootnodes()
123 }
124
125 fn is_optimism(&self) -> bool {
126 false
127 }
128
129 fn final_paris_total_difficulty(&self) -> Option<U256> {
130 self.get_final_paris_total_difficulty()
131 }
132}