custom_hardforks/
chainspec.rs

1//! Custom chain specification integrating hardforks.
2//!
3//! This demonstrates how to build a `ChainSpec` with custom hardforks,
4//! implementing required traits for integration with Reth's chain management.
5
6use alloy_eips::eip7840::BlobParams;
7use alloy_genesis::Genesis;
8use alloy_primitives::{B256, U256};
9use reth_chainspec::{
10    hardfork, BaseFeeParams, Chain, ChainSpec, DepositContract, EthChainSpec, EthereumHardfork,
11    EthereumHardforks, ForkCondition, Hardfork, Hardforks,
12};
13use reth_network_peers::NodeRecord;
14use serde::{Deserialize, Serialize};
15
16// Define custom hardfork variants using Reth's `hardfork!` macro.
17// Each variant represents a protocol upgrade (e.g., enabling new features).
18hardfork!(
19    /// Custom hardforks for the example chain.
20    ///
21    /// These are inspired by Ethereum's upgrades but customized for demonstration.
22    /// Add new variants here to extend the chain's hardfork set.
23    CustomHardfork {
24        /// Enables basic custom features (e.g., a new precompile).
25        BasicUpgrade,
26        /// Enables advanced features (e.g., state modifications).
27        AdvancedUpgrade,
28    }
29);
30
31// Implement the `Hardfork` trait for each variant.
32// This defines the name and any custom logic (e.g., feature toggles).
33// Note: The hardfork! macro already implements Hardfork, so no manual impl needed.
34
35// Configuration for hardfork activation.
36// This struct holds settings like activation blocks and is serializable for config files.
37#[derive(Debug, Clone, Serialize, Deserialize, Default)]
38#[serde(rename_all = "camelCase")]
39pub struct CustomHardforkConfig {
40    /// Block number to activate BasicUpgrade.
41    pub basic_upgrade_block: u64,
42    /// Block number to activate AdvancedUpgrade.
43    pub advanced_upgrade_block: u64,
44}
45
46// Custom chain spec wrapping Reth's `ChainSpec` with our hardforks.
47#[derive(Debug, Clone)]
48pub struct CustomChainSpec {
49    pub inner: ChainSpec,
50}
51
52impl CustomChainSpec {
53    /// Creates a custom chain spec from a genesis file.
54    ///
55    /// This parses the [`ChainSpec`] and adds the custom hardforks.
56    pub fn from_genesis(genesis: Genesis) -> Self {
57        let extra = genesis.config.extra_fields.deserialize_as::<CustomHardforkConfig>().unwrap();
58
59        let mut inner = ChainSpec::from_genesis(genesis);
60        inner.hardforks.insert(
61            CustomHardfork::BasicUpgrade,
62            ForkCondition::Timestamp(extra.basic_upgrade_block),
63        );
64        inner.hardforks.insert(
65            CustomHardfork::AdvancedUpgrade,
66            ForkCondition::Timestamp(extra.advanced_upgrade_block),
67        );
68        Self { inner }
69    }
70}
71
72// Implement `Hardforks` to integrate custom hardforks with Reth's system.
73impl Hardforks for CustomChainSpec {
74    fn fork<H: Hardfork>(&self, fork: H) -> ForkCondition {
75        self.inner.fork(fork)
76    }
77
78    fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, ForkCondition)> {
79        self.inner.forks_iter()
80    }
81
82    fn fork_id(&self, head: &reth_chainspec::Head) -> reth_chainspec::ForkId {
83        self.inner.fork_id(head)
84    }
85
86    fn latest_fork_id(&self) -> reth_chainspec::ForkId {
87        self.inner.latest_fork_id()
88    }
89
90    fn fork_filter(&self, head: reth_chainspec::Head) -> reth_chainspec::ForkFilter {
91        self.inner.fork_filter(head)
92    }
93}
94
95// Implement `EthChainSpec` for compatibility with Ethereum-based nodes.
96impl EthChainSpec for CustomChainSpec {
97    type Header = alloy_consensus::Header;
98
99    fn chain(&self) -> Chain {
100        self.inner.chain()
101    }
102
103    fn base_fee_params_at_timestamp(&self, timestamp: u64) -> BaseFeeParams {
104        self.inner.base_fee_params_at_timestamp(timestamp)
105    }
106
107    fn blob_params_at_timestamp(&self, timestamp: u64) -> Option<BlobParams> {
108        self.inner.blob_params_at_timestamp(timestamp)
109    }
110
111    fn deposit_contract(&self) -> Option<&DepositContract> {
112        self.inner.deposit_contract()
113    }
114
115    fn genesis_hash(&self) -> B256 {
116        self.inner.genesis_hash()
117    }
118
119    fn prune_delete_limit(&self) -> usize {
120        self.inner.prune_delete_limit()
121    }
122
123    fn display_hardforks(&self) -> Box<dyn core::fmt::Display> {
124        Box::new(self.inner.display_hardforks())
125    }
126
127    fn genesis_header(&self) -> &Self::Header {
128        self.inner.genesis_header()
129    }
130
131    fn genesis(&self) -> &Genesis {
132        self.inner.genesis()
133    }
134
135    fn bootnodes(&self) -> Option<Vec<NodeRecord>> {
136        self.inner.bootnodes()
137    }
138
139    fn final_paris_total_difficulty(&self) -> Option<U256> {
140        self.inner.final_paris_total_difficulty()
141    }
142}
143
144// Implement `EthereumHardforks` to support Ethereum hardfork queries.
145impl EthereumHardforks for CustomChainSpec {
146    fn ethereum_fork_activation(&self, fork: EthereumHardfork) -> ForkCondition {
147        self.inner.ethereum_fork_activation(fork)
148    }
149}