mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-10 07:48:19 -05:00
fix(chainspec): add ChainConfig to StatelessInput and add ChainConfig creator helpers (#20101)
Signed-off-by: Ignacio Hagopian <jsign.uy@gmail.com>
This commit is contained in:
5
Cargo.lock
generated
5
Cargo.lock
generated
@@ -303,9 +303,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "alloy-hardforks"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e29d7eacf42f89c21d7f089916d0bdb4f36139a31698790e8837d2dbbd4b2c3"
|
||||
checksum = "2d9a33550fc21fd77a3f8b63e99969d17660eec8dcc50a95a80f7c9964f7680b"
|
||||
dependencies = [
|
||||
"alloy-chains",
|
||||
"alloy-eip2124",
|
||||
@@ -10566,6 +10566,7 @@ name = "reth-stateless"
|
||||
version = "1.9.3"
|
||||
dependencies = [
|
||||
"alloy-consensus",
|
||||
"alloy-genesis",
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
"alloy-rpc-types-debug",
|
||||
|
||||
@@ -493,7 +493,7 @@ alloy-sol-macro = "1.4.1"
|
||||
alloy-sol-types = { version = "1.4.1", default-features = false }
|
||||
alloy-trie = { version = "0.9.1", default-features = false }
|
||||
|
||||
alloy-hardforks = "0.4.4"
|
||||
alloy-hardforks = "0.4.5"
|
||||
|
||||
alloy-consensus = { version = "1.1.2", default-features = false }
|
||||
alloy-contract = { version = "1.1.2", default-features = false }
|
||||
|
||||
@@ -30,8 +30,9 @@ pub use info::ChainInfo;
|
||||
#[cfg(any(test, feature = "test-utils"))]
|
||||
pub use spec::test_fork_ids;
|
||||
pub use spec::{
|
||||
make_genesis_header, BaseFeeParams, BaseFeeParamsKind, ChainSpec, ChainSpecBuilder,
|
||||
ChainSpecProvider, DepositContract, ForkBaseFeeParams, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA,
|
||||
blob_params_to_schedule, create_chain_config, mainnet_chain_config, make_genesis_header,
|
||||
BaseFeeParams, BaseFeeParamsKind, ChainSpec, ChainSpecBuilder, ChainSpecProvider,
|
||||
DepositContract, ForkBaseFeeParams, DEV, HOLESKY, HOODI, MAINNET, SEPOLIA,
|
||||
};
|
||||
|
||||
use reth_primitives_traits::sync::OnceLock;
|
||||
|
||||
@@ -10,7 +10,14 @@ use crate::{
|
||||
sepolia::SEPOLIA_PARIS_BLOCK,
|
||||
EthChainSpec,
|
||||
};
|
||||
use alloc::{boxed::Box, format, sync::Arc, vec::Vec};
|
||||
use alloc::{
|
||||
boxed::Box,
|
||||
collections::BTreeMap,
|
||||
format,
|
||||
string::{String, ToString},
|
||||
sync::Arc,
|
||||
vec::Vec,
|
||||
};
|
||||
use alloy_chains::{Chain, NamedChain};
|
||||
use alloy_consensus::{
|
||||
constants::{
|
||||
@@ -23,7 +30,7 @@ use alloy_eips::{
|
||||
eip1559::INITIAL_BASE_FEE, eip7685::EMPTY_REQUESTS_HASH, eip7840::BlobParams,
|
||||
eip7892::BlobScheduleBlobParams,
|
||||
};
|
||||
use alloy_genesis::Genesis;
|
||||
use alloy_genesis::{ChainConfig, Genesis};
|
||||
use alloy_primitives::{address, b256, Address, BlockNumber, B256, U256};
|
||||
use alloy_trie::root::state_root_ref_unhashed;
|
||||
use core::fmt::Debug;
|
||||
@@ -240,6 +247,111 @@ pub static DEV: LazyLock<Arc<ChainSpec>> = LazyLock::new(|| {
|
||||
.into()
|
||||
});
|
||||
|
||||
/// Creates a [`ChainConfig`] from the given chain, hardforks, deposit contract address, and blob
|
||||
/// schedule.
|
||||
pub fn create_chain_config(
|
||||
chain: Option<Chain>,
|
||||
hardforks: &ChainHardforks,
|
||||
deposit_contract_address: Option<Address>,
|
||||
blob_schedule: BTreeMap<String, BlobParams>,
|
||||
) -> ChainConfig {
|
||||
// Helper to extract block number from a hardfork condition
|
||||
let block_num = |fork: EthereumHardfork| hardforks.fork(fork).block_number();
|
||||
|
||||
// Helper to extract timestamp from a hardfork condition
|
||||
let timestamp = |fork: EthereumHardfork| -> Option<u64> {
|
||||
match hardforks.fork(fork) {
|
||||
ForkCondition::Timestamp(t) => Some(t),
|
||||
_ => None,
|
||||
}
|
||||
};
|
||||
|
||||
// Extract TTD from Paris fork
|
||||
let (terminal_total_difficulty, terminal_total_difficulty_passed) =
|
||||
match hardforks.fork(EthereumHardfork::Paris) {
|
||||
ForkCondition::TTD { total_difficulty, .. } => (Some(total_difficulty), true),
|
||||
_ => (None, false),
|
||||
};
|
||||
|
||||
// Check if DAO fork is supported (it has an activation block)
|
||||
let dao_fork_support = hardforks.fork(EthereumHardfork::Dao) != ForkCondition::Never;
|
||||
|
||||
ChainConfig {
|
||||
chain_id: chain.map(|c| c.id()).unwrap_or(0),
|
||||
homestead_block: block_num(EthereumHardfork::Homestead),
|
||||
dao_fork_block: block_num(EthereumHardfork::Dao),
|
||||
dao_fork_support,
|
||||
eip150_block: block_num(EthereumHardfork::Tangerine),
|
||||
eip155_block: block_num(EthereumHardfork::SpuriousDragon),
|
||||
eip158_block: block_num(EthereumHardfork::SpuriousDragon),
|
||||
byzantium_block: block_num(EthereumHardfork::Byzantium),
|
||||
constantinople_block: block_num(EthereumHardfork::Constantinople),
|
||||
petersburg_block: block_num(EthereumHardfork::Petersburg),
|
||||
istanbul_block: block_num(EthereumHardfork::Istanbul),
|
||||
muir_glacier_block: block_num(EthereumHardfork::MuirGlacier),
|
||||
berlin_block: block_num(EthereumHardfork::Berlin),
|
||||
london_block: block_num(EthereumHardfork::London),
|
||||
arrow_glacier_block: block_num(EthereumHardfork::ArrowGlacier),
|
||||
gray_glacier_block: block_num(EthereumHardfork::GrayGlacier),
|
||||
merge_netsplit_block: None,
|
||||
shanghai_time: timestamp(EthereumHardfork::Shanghai),
|
||||
cancun_time: timestamp(EthereumHardfork::Cancun),
|
||||
prague_time: timestamp(EthereumHardfork::Prague),
|
||||
osaka_time: timestamp(EthereumHardfork::Osaka),
|
||||
bpo1_time: timestamp(EthereumHardfork::Bpo1),
|
||||
bpo2_time: timestamp(EthereumHardfork::Bpo2),
|
||||
bpo3_time: timestamp(EthereumHardfork::Bpo3),
|
||||
bpo4_time: timestamp(EthereumHardfork::Bpo4),
|
||||
bpo5_time: timestamp(EthereumHardfork::Bpo5),
|
||||
terminal_total_difficulty,
|
||||
terminal_total_difficulty_passed,
|
||||
ethash: None,
|
||||
clique: None,
|
||||
parlia: None,
|
||||
extra_fields: Default::default(),
|
||||
deposit_contract_address,
|
||||
blob_schedule,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a [`ChainConfig`] for the current Ethereum mainnet chain.
|
||||
pub fn mainnet_chain_config() -> ChainConfig {
|
||||
let hardforks: ChainHardforks = EthereumHardfork::mainnet().into();
|
||||
let blob_schedule = blob_params_to_schedule(&MAINNET.blob_params, &hardforks);
|
||||
create_chain_config(
|
||||
Some(Chain::mainnet()),
|
||||
&hardforks,
|
||||
Some(MAINNET_DEPOSIT_CONTRACT.address),
|
||||
blob_schedule,
|
||||
)
|
||||
}
|
||||
|
||||
/// Converts the given [`BlobScheduleBlobParams`] into blobs schedule.
|
||||
pub fn blob_params_to_schedule(
|
||||
params: &BlobScheduleBlobParams,
|
||||
hardforks: &ChainHardforks,
|
||||
) -> BTreeMap<String, BlobParams> {
|
||||
let mut schedule = BTreeMap::new();
|
||||
schedule.insert("cancun".to_string(), params.cancun);
|
||||
schedule.insert("prague".to_string(), params.prague);
|
||||
schedule.insert("osaka".to_string(), params.osaka);
|
||||
|
||||
// Map scheduled entries back to bpo fork names by matching timestamps
|
||||
let bpo_forks = EthereumHardfork::bpo_variants();
|
||||
for (timestamp, blob_params) in ¶ms.scheduled {
|
||||
for bpo_fork in bpo_forks {
|
||||
if let ForkCondition::Timestamp(fork_ts) = hardforks.fork(bpo_fork) &&
|
||||
fork_ts == *timestamp
|
||||
{
|
||||
schedule.insert(bpo_fork.name().to_lowercase(), *blob_params);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
schedule
|
||||
}
|
||||
|
||||
/// A wrapper around [`BaseFeeParams`] that allows for specifying constant or dynamic EIP-1559
|
||||
/// parameters based on the active [Hardfork].
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
@@ -936,9 +1048,16 @@ impl ChainSpecBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable Dao at genesis.
|
||||
pub fn dao_activated(mut self) -> Self {
|
||||
self = self.frontier_activated();
|
||||
self.hardforks.insert(EthereumHardfork::Dao, ForkCondition::Block(0));
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable Homestead at genesis.
|
||||
pub fn homestead_activated(mut self) -> Self {
|
||||
self = self.frontier_activated();
|
||||
self = self.dao_activated();
|
||||
self.hardforks.insert(EthereumHardfork::Homestead, ForkCondition::Block(0));
|
||||
self
|
||||
}
|
||||
@@ -985,9 +1104,16 @@ impl ChainSpecBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable Muir Glacier at genesis.
|
||||
pub fn muirglacier_activated(mut self) -> Self {
|
||||
self = self.istanbul_activated();
|
||||
self.hardforks.insert(EthereumHardfork::MuirGlacier, ForkCondition::Block(0));
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable Berlin at genesis.
|
||||
pub fn berlin_activated(mut self) -> Self {
|
||||
self = self.istanbul_activated();
|
||||
self = self.muirglacier_activated();
|
||||
self.hardforks.insert(EthereumHardfork::Berlin, ForkCondition::Block(0));
|
||||
self
|
||||
}
|
||||
@@ -999,9 +1125,23 @@ impl ChainSpecBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable Arrow Glacier at genesis.
|
||||
pub fn arrowglacier_activated(mut self) -> Self {
|
||||
self = self.london_activated();
|
||||
self.hardforks.insert(EthereumHardfork::ArrowGlacier, ForkCondition::Block(0));
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable Gray Glacier at genesis.
|
||||
pub fn grayglacier_activated(mut self) -> Self {
|
||||
self = self.arrowglacier_activated();
|
||||
self.hardforks.insert(EthereumHardfork::GrayGlacier, ForkCondition::Block(0));
|
||||
self
|
||||
}
|
||||
|
||||
/// Enable Paris at genesis.
|
||||
pub fn paris_activated(mut self) -> Self {
|
||||
self = self.london_activated();
|
||||
self = self.grayglacier_activated();
|
||||
self.hardforks.insert(
|
||||
EthereumHardfork::Paris,
|
||||
ForkCondition::TTD {
|
||||
|
||||
@@ -18,6 +18,7 @@ alloy-rlp.workspace = true
|
||||
alloy-trie.workspace = true
|
||||
alloy-consensus.workspace = true
|
||||
alloy-rpc-types-debug.workspace = true
|
||||
alloy-genesis = { workspace = true, features = ["serde-bincode-compat"] }
|
||||
|
||||
# reth
|
||||
reth-ethereum-consensus.workspace = true
|
||||
|
||||
@@ -39,6 +39,7 @@ mod recover_block;
|
||||
/// Sparse trie implementation for stateless validation
|
||||
pub mod trie;
|
||||
|
||||
use alloy_genesis::ChainConfig;
|
||||
#[doc(inline)]
|
||||
pub use recover_block::UncompressedPublicKey;
|
||||
#[doc(inline)]
|
||||
@@ -55,6 +56,8 @@ pub(crate) mod witness_db;
|
||||
#[doc(inline)]
|
||||
pub use alloy_rpc_types_debug::ExecutionWitness;
|
||||
|
||||
pub use alloy_genesis::Genesis;
|
||||
|
||||
use reth_ethereum_primitives::Block;
|
||||
|
||||
/// `StatelessInput` is a convenience structure for serializing the input needed
|
||||
@@ -69,4 +72,7 @@ pub struct StatelessInput {
|
||||
pub block: Block,
|
||||
/// `ExecutionWitness` for the stateless validation function
|
||||
pub witness: ExecutionWitness,
|
||||
/// Chain configuration for the stateless validation function
|
||||
#[serde_as(as = "alloy_genesis::serde_bincode_compat::ChainConfig<'_>")]
|
||||
pub chain_config: ChainConfig,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user