mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: use new ChainHardforks type on ChainSpec (#9065)
This commit is contained in:
4
Cargo.lock
generated
4
Cargo.lock
generated
@ -7083,9 +7083,13 @@ dependencies = [
|
||||
"alloy-primitives",
|
||||
"alloy-rlp",
|
||||
"arbitrary",
|
||||
"auto_impl",
|
||||
"crc",
|
||||
"dyn-clone",
|
||||
"once_cell",
|
||||
"proptest",
|
||||
"proptest-derive 0.5.0",
|
||||
"rustc-hash 2.0.0",
|
||||
"serde",
|
||||
"thiserror-no-std",
|
||||
]
|
||||
|
||||
@ -15,8 +15,8 @@ use reth_evm::execute::BlockExecutorProvider;
|
||||
use reth_execution_errors::{BlockExecutionError, BlockValidationError};
|
||||
use reth_execution_types::{Chain, ExecutionOutcome};
|
||||
use reth_primitives::{
|
||||
BlockHash, BlockNumHash, BlockNumber, ForkBlock, GotExpected, Hardfork, Receipt, SealedBlock,
|
||||
SealedBlockWithSenders, SealedHeader, StaticFileSegment, B256, U256,
|
||||
BlockHash, BlockNumHash, BlockNumber, EthereumHardfork, ForkBlock, GotExpected, Receipt,
|
||||
SealedBlock, SealedBlockWithSenders, SealedHeader, StaticFileSegment, B256, U256,
|
||||
};
|
||||
use reth_provider::{
|
||||
BlockExecutionWriter, BlockNumReader, BlockWriter, CanonStateNotification,
|
||||
@ -402,7 +402,7 @@ where
|
||||
.externals
|
||||
.provider_factory
|
||||
.chain_spec()
|
||||
.fork(Hardfork::Paris)
|
||||
.fork(EthereumHardfork::Paris)
|
||||
.active_at_ttd(parent_td, U256::ZERO)
|
||||
{
|
||||
return Err(BlockExecutionError::Validation(BlockValidationError::BlockPreMerge {
|
||||
@ -1043,7 +1043,7 @@ where
|
||||
.externals
|
||||
.provider_factory
|
||||
.chain_spec()
|
||||
.fork(Hardfork::Paris)
|
||||
.fork(EthereumHardfork::Paris)
|
||||
.active_at_ttd(td, U256::ZERO)
|
||||
{
|
||||
return Err(CanonicalError::from(BlockValidationError::BlockPreMerge {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,7 @@
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
|
||||
use reth_beacon_consensus::BeaconEngineMessage;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_consensus::{Consensus, ConsensusError, PostExecutionInput};
|
||||
use reth_engine_primitives::EngineTypes;
|
||||
use reth_execution_errors::{BlockExecutionError, BlockValidationError};
|
||||
|
||||
@ -2492,7 +2492,7 @@ mod tests {
|
||||
use super::*;
|
||||
use alloy_genesis::Genesis;
|
||||
use reth_db::test_utils::create_test_static_files_dir;
|
||||
use reth_primitives::{Hardfork, U256};
|
||||
use reth_primitives::{EthereumHardfork, U256};
|
||||
use reth_provider::{
|
||||
providers::StaticFileProvider, test_utils::blocks::BlockchainTestData,
|
||||
};
|
||||
@ -2721,9 +2721,9 @@ mod tests {
|
||||
async fn payload_pre_merge() {
|
||||
let data = BlockchainTestData::default();
|
||||
let mut block1 = data.blocks[0].0.block.clone();
|
||||
block1
|
||||
.header
|
||||
.set_difficulty(MAINNET.fork(Hardfork::Paris).ttd().unwrap() - U256::from(1));
|
||||
block1.header.set_difficulty(
|
||||
MAINNET.fork(EthereumHardfork::Paris).ttd().unwrap() - U256::from(1),
|
||||
);
|
||||
block1 = block1.unseal().seal_slow();
|
||||
let (block2, exec_result2) = data.blocks[1].clone();
|
||||
let mut block2 = block2.unseal().block;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use reth_chainspec::{Chain, ChainSpec, Hardfork};
|
||||
use reth_chainspec::{Chain, ChainSpec, EthereumHardfork};
|
||||
use reth_primitives::{constants::ETH_TO_WEI, BlockNumber, U256};
|
||||
|
||||
/// Calculates the base block reward.
|
||||
@ -26,7 +26,7 @@ pub fn base_block_reward(
|
||||
block_difficulty: U256,
|
||||
total_difficulty: U256,
|
||||
) -> Option<u128> {
|
||||
if chain_spec.fork(Hardfork::Paris).active_at_ttd(total_difficulty, block_difficulty) ||
|
||||
if chain_spec.fork(EthereumHardfork::Paris).active_at_ttd(total_difficulty, block_difficulty) ||
|
||||
chain_spec.chain == Chain::goerli()
|
||||
{
|
||||
None
|
||||
@ -39,9 +39,9 @@ pub fn base_block_reward(
|
||||
///
|
||||
/// Caution: The caller must ensure that the block number is before the merge.
|
||||
pub fn base_block_reward_pre_merge(chain_spec: &ChainSpec, block_number: BlockNumber) -> u128 {
|
||||
if chain_spec.fork(Hardfork::Constantinople).active_at_block(block_number) {
|
||||
if chain_spec.fork(EthereumHardfork::Constantinople).active_at_block(block_number) {
|
||||
ETH_TO_WEI * 2
|
||||
} else if chain_spec.fork(Hardfork::Byzantium).active_at_block(block_number) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Byzantium).active_at_block(block_number) {
|
||||
ETH_TO_WEI * 3
|
||||
} else {
|
||||
ETH_TO_WEI * 5
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
//! Collection of methods for block validation.
|
||||
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_consensus::ConsensusError;
|
||||
use reth_primitives::{
|
||||
constants::{
|
||||
@ -8,7 +8,7 @@ use reth_primitives::{
|
||||
MAXIMUM_EXTRA_DATA_SIZE,
|
||||
},
|
||||
eip4844::calculate_excess_blob_gas,
|
||||
GotExpected, Hardfork, Header, SealedBlock, SealedHeader,
|
||||
EthereumHardfork, GotExpected, Header, SealedBlock, SealedHeader,
|
||||
};
|
||||
|
||||
/// Gas used needs to be less than gas limit. Gas used is going to be checked after execution.
|
||||
@ -29,7 +29,7 @@ pub fn validate_header_base_fee(
|
||||
header: &SealedHeader,
|
||||
chain_spec: &ChainSpec,
|
||||
) -> Result<(), ConsensusError> {
|
||||
if chain_spec.fork(Hardfork::London).active_at_block(header.number) &&
|
||||
if chain_spec.fork(EthereumHardfork::London).active_at_block(header.number) &&
|
||||
header.base_fee_per_gas.is_none()
|
||||
{
|
||||
return Err(ConsensusError::BaseFeeMissing)
|
||||
@ -192,11 +192,11 @@ pub fn validate_against_parent_eip1559_base_fee(
|
||||
parent: &SealedHeader,
|
||||
chain_spec: &ChainSpec,
|
||||
) -> Result<(), ConsensusError> {
|
||||
if chain_spec.fork(Hardfork::London).active_at_block(header.number) {
|
||||
if chain_spec.fork(EthereumHardfork::London).active_at_block(header.number) {
|
||||
let base_fee = header.base_fee_per_gas.ok_or(ConsensusError::BaseFeeMissing)?;
|
||||
|
||||
let expected_base_fee =
|
||||
if chain_spec.fork(Hardfork::London).transitions_at_block(header.number) {
|
||||
if chain_spec.fork(EthereumHardfork::London).transitions_at_block(header.number) {
|
||||
reth_primitives::constants::EIP1559_INITIAL_BASE_FEE
|
||||
} else {
|
||||
// This BaseFeeMissing will not happen as previous blocks are checked to have
|
||||
|
||||
@ -23,11 +23,15 @@ crc = "3"
|
||||
# misc
|
||||
serde = { workspace = true, features = ["derive"], optional = true }
|
||||
thiserror-no-std = { workspace = true, default-features = false }
|
||||
once_cell.workspace = true
|
||||
dyn-clone.workspace = true
|
||||
rustc-hash.workspace = true
|
||||
|
||||
# arbitrary utils
|
||||
arbitrary = { workspace = true, features = ["derive"], optional = true }
|
||||
proptest = { workspace = true, optional = true }
|
||||
proptest-derive = { workspace = true, optional = true }
|
||||
auto_impl.workspace = true
|
||||
|
||||
[dev-dependencies]
|
||||
arbitrary = { workspace = true, features = ["derive"] }
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
use crate::{ForkCondition, Hardfork};
|
||||
use alloy_primitives::uint;
|
||||
|
||||
/// Dev hardforks
|
||||
pub const DEV_HARDFORKS: [(Hardfork, ForkCondition); 14] = [
|
||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||
(Hardfork::Dao, ForkCondition::Block(0)),
|
||||
(Hardfork::Tangerine, ForkCondition::Block(0)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(0)),
|
||||
(Hardfork::Constantinople, ForkCondition::Block(0)),
|
||||
(Hardfork::Petersburg, ForkCondition::Block(0)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(1561651)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(4460644)),
|
||||
(Hardfork::London, ForkCondition::Block(5062605)),
|
||||
(
|
||||
Hardfork::Paris,
|
||||
ForkCondition::TTD { fork_block: None, total_difficulty: uint!(10_790_000_U256) },
|
||||
),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1678832736)),
|
||||
(Hardfork::Cancun, ForkCondition::Timestamp(1705473120)),
|
||||
];
|
||||
@ -1,94 +0,0 @@
|
||||
use crate::{ForkCondition, Hardfork};
|
||||
use alloy_primitives::{uint, U256};
|
||||
|
||||
/// Ethereum mainnet hardforks
|
||||
pub const MAINNET_HARDFORKS: [(Hardfork, ForkCondition); 17] = [
|
||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||
(Hardfork::Homestead, ForkCondition::Block(1150000)),
|
||||
(Hardfork::Dao, ForkCondition::Block(1920000)),
|
||||
(Hardfork::Tangerine, ForkCondition::Block(2463000)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(2675000)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(4370000)),
|
||||
(Hardfork::Constantinople, ForkCondition::Block(7280000)),
|
||||
(Hardfork::Petersburg, ForkCondition::Block(7280000)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(9069000)),
|
||||
(Hardfork::MuirGlacier, ForkCondition::Block(9200000)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(12244000)),
|
||||
(Hardfork::London, ForkCondition::Block(12965000)),
|
||||
(Hardfork::ArrowGlacier, ForkCondition::Block(13773000)),
|
||||
(Hardfork::GrayGlacier, ForkCondition::Block(15050000)),
|
||||
(
|
||||
Hardfork::Paris,
|
||||
ForkCondition::TTD {
|
||||
fork_block: None,
|
||||
total_difficulty: uint!(58_750_000_000_000_000_000_000_U256),
|
||||
},
|
||||
),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1681338455)),
|
||||
(Hardfork::Cancun, ForkCondition::Timestamp(1710338135)),
|
||||
];
|
||||
|
||||
/// Ethereum Goerli hardforks
|
||||
pub const GOERLI_HARDFORKS: [(Hardfork, ForkCondition); 14] = [
|
||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||
(Hardfork::Dao, ForkCondition::Block(0)),
|
||||
(Hardfork::Tangerine, ForkCondition::Block(0)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(0)),
|
||||
(Hardfork::Constantinople, ForkCondition::Block(0)),
|
||||
(Hardfork::Petersburg, ForkCondition::Block(0)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(1561651)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(4460644)),
|
||||
(Hardfork::London, ForkCondition::Block(5062605)),
|
||||
(
|
||||
Hardfork::Paris,
|
||||
ForkCondition::TTD { fork_block: None, total_difficulty: uint!(10_790_000_U256) },
|
||||
),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1678832736)),
|
||||
(Hardfork::Cancun, ForkCondition::Timestamp(1705473120)),
|
||||
];
|
||||
|
||||
/// Ethereum Sepolia hardforks
|
||||
pub const SEPOLIA_HARDFORKS: [(Hardfork, ForkCondition); 15] = [
|
||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||
(Hardfork::Dao, ForkCondition::Block(0)),
|
||||
(Hardfork::Tangerine, ForkCondition::Block(0)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(0)),
|
||||
(Hardfork::Constantinople, ForkCondition::Block(0)),
|
||||
(Hardfork::Petersburg, ForkCondition::Block(0)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(0)),
|
||||
(Hardfork::MuirGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(0)),
|
||||
(Hardfork::London, ForkCondition::Block(0)),
|
||||
(
|
||||
Hardfork::Paris,
|
||||
ForkCondition::TTD {
|
||||
fork_block: Some(1735371),
|
||||
total_difficulty: uint!(17_000_000_000_000_000_U256),
|
||||
},
|
||||
),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1677557088)),
|
||||
(Hardfork::Cancun, ForkCondition::Timestamp(1706655072)),
|
||||
];
|
||||
|
||||
/// Ethereum Holesky hardforks
|
||||
pub const HOLESKY_HARDFORKS: [(Hardfork, ForkCondition); 15] = [
|
||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||
(Hardfork::Dao, ForkCondition::Block(0)),
|
||||
(Hardfork::Tangerine, ForkCondition::Block(0)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(0)),
|
||||
(Hardfork::Constantinople, ForkCondition::Block(0)),
|
||||
(Hardfork::Petersburg, ForkCondition::Block(0)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(0)),
|
||||
(Hardfork::MuirGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(0)),
|
||||
(Hardfork::London, ForkCondition::Block(0)),
|
||||
(Hardfork::Paris, ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO }),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1696000704)),
|
||||
(Hardfork::Cancun, ForkCondition::Timestamp(1707305664)),
|
||||
];
|
||||
@ -1,9 +0,0 @@
|
||||
/// Ethereum chains
|
||||
pub mod ethereum;
|
||||
|
||||
/// Optimism chains
|
||||
#[cfg(feature = "optimism")]
|
||||
pub mod optimism;
|
||||
|
||||
/// Dev chain
|
||||
pub mod dev;
|
||||
@ -1,105 +0,0 @@
|
||||
use crate::{ForkCondition, Hardfork};
|
||||
use alloy_primitives::U256;
|
||||
|
||||
/// Optimism mainnet hardforks
|
||||
pub const OP_MAINNET_HARDFORKS: [(Hardfork, ForkCondition); 21] = [
|
||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||
(Hardfork::Tangerine, ForkCondition::Block(0)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(0)),
|
||||
(Hardfork::Constantinople, ForkCondition::Block(0)),
|
||||
(Hardfork::Petersburg, ForkCondition::Block(0)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(0)),
|
||||
(Hardfork::MuirGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(3950000)),
|
||||
(Hardfork::London, ForkCondition::Block(105235063)),
|
||||
(Hardfork::ArrowGlacier, ForkCondition::Block(105235063)),
|
||||
(Hardfork::GrayGlacier, ForkCondition::Block(105235063)),
|
||||
(
|
||||
Hardfork::Paris,
|
||||
ForkCondition::TTD { fork_block: Some(105235063), total_difficulty: U256::ZERO },
|
||||
),
|
||||
(Hardfork::Bedrock, ForkCondition::Block(105235063)),
|
||||
(Hardfork::Regolith, ForkCondition::Timestamp(0)),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1704992401)),
|
||||
(Hardfork::Canyon, ForkCondition::Timestamp(1704992401)),
|
||||
(Hardfork::Cancun, ForkCondition::Timestamp(1710374401)),
|
||||
(Hardfork::Ecotone, ForkCondition::Timestamp(1710374401)),
|
||||
(Hardfork::Fjord, ForkCondition::Timestamp(1720627201)),
|
||||
];
|
||||
|
||||
/// Optimism Sepolia hardforks
|
||||
pub const OP_SEPOLIA_HARDFORKS: [(Hardfork, ForkCondition); 21] = [
|
||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||
(Hardfork::Tangerine, ForkCondition::Block(0)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(0)),
|
||||
(Hardfork::Constantinople, ForkCondition::Block(0)),
|
||||
(Hardfork::Petersburg, ForkCondition::Block(0)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(0)),
|
||||
(Hardfork::MuirGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(0)),
|
||||
(Hardfork::London, ForkCondition::Block(0)),
|
||||
(Hardfork::ArrowGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::GrayGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::Paris, ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO }),
|
||||
(Hardfork::Bedrock, ForkCondition::Block(0)),
|
||||
(Hardfork::Regolith, ForkCondition::Timestamp(0)),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1699981200)),
|
||||
(Hardfork::Canyon, ForkCondition::Timestamp(1699981200)),
|
||||
(Hardfork::Cancun, ForkCondition::Timestamp(1708534800)),
|
||||
(Hardfork::Ecotone, ForkCondition::Timestamp(1708534800)),
|
||||
(Hardfork::Fjord, ForkCondition::Timestamp(1716998400)),
|
||||
];
|
||||
|
||||
/// Base Sepolia hardforks
|
||||
pub const BASE_SEPOLIA_HARDFORKS: [(Hardfork, ForkCondition); 21] = [
|
||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||
(Hardfork::Tangerine, ForkCondition::Block(0)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(0)),
|
||||
(Hardfork::Constantinople, ForkCondition::Block(0)),
|
||||
(Hardfork::Petersburg, ForkCondition::Block(0)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(0)),
|
||||
(Hardfork::MuirGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(0)),
|
||||
(Hardfork::London, ForkCondition::Block(0)),
|
||||
(Hardfork::ArrowGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::GrayGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::Paris, ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO }),
|
||||
(Hardfork::Bedrock, ForkCondition::Block(0)),
|
||||
(Hardfork::Regolith, ForkCondition::Timestamp(0)),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1699981200)),
|
||||
(Hardfork::Canyon, ForkCondition::Timestamp(1699981200)),
|
||||
(Hardfork::Cancun, ForkCondition::Timestamp(1708534800)),
|
||||
(Hardfork::Ecotone, ForkCondition::Timestamp(1708534800)),
|
||||
(Hardfork::Fjord, ForkCondition::Timestamp(1716998400)),
|
||||
];
|
||||
|
||||
/// Base Mainnet hardforks
|
||||
pub const BASE_MAINNET_HARDFORKS: [(Hardfork, ForkCondition); 21] = [
|
||||
(Hardfork::Frontier, ForkCondition::Block(0)),
|
||||
(Hardfork::Homestead, ForkCondition::Block(0)),
|
||||
(Hardfork::Tangerine, ForkCondition::Block(0)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(0)),
|
||||
(Hardfork::Constantinople, ForkCondition::Block(0)),
|
||||
(Hardfork::Petersburg, ForkCondition::Block(0)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(0)),
|
||||
(Hardfork::MuirGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(0)),
|
||||
(Hardfork::London, ForkCondition::Block(0)),
|
||||
(Hardfork::ArrowGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::GrayGlacier, ForkCondition::Block(0)),
|
||||
(Hardfork::Paris, ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO }),
|
||||
(Hardfork::Bedrock, ForkCondition::Block(0)),
|
||||
(Hardfork::Regolith, ForkCondition::Timestamp(0)),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(1704992401)),
|
||||
(Hardfork::Canyon, ForkCondition::Timestamp(1704992401)),
|
||||
(Hardfork::Cancun, ForkCondition::Timestamp(1710374401)),
|
||||
(Hardfork::Ecotone, ForkCondition::Timestamp(1710374401)),
|
||||
(Hardfork::Fjord, ForkCondition::Timestamp(1720627201)),
|
||||
];
|
||||
@ -6,9 +6,7 @@ use alloc::{
|
||||
vec::Vec,
|
||||
};
|
||||
|
||||
use crate::{ForkCondition, Hardfork};
|
||||
#[cfg(feature = "std")]
|
||||
use std::collections::BTreeMap;
|
||||
use crate::{hardforks::Hardforks, ForkCondition};
|
||||
|
||||
/// A container to pretty-print a hardfork.
|
||||
///
|
||||
@ -146,27 +144,22 @@ impl core::fmt::Display for DisplayHardforks {
|
||||
|
||||
impl DisplayHardforks {
|
||||
/// Creates a new [`DisplayHardforks`] from an iterator of hardforks.
|
||||
pub fn new(
|
||||
hardforks: &BTreeMap<Hardfork, ForkCondition>,
|
||||
known_paris_block: Option<u64>,
|
||||
) -> Self {
|
||||
pub fn new<H: Hardforks>(hardforks: &H, known_paris_block: Option<u64>) -> Self {
|
||||
let mut pre_merge = Vec::new();
|
||||
let mut with_merge = Vec::new();
|
||||
let mut post_merge = Vec::new();
|
||||
|
||||
for (fork, condition) in hardforks {
|
||||
for (fork, condition) in hardforks.forks_iter() {
|
||||
let mut display_fork =
|
||||
DisplayFork { name: fork.to_string(), activated_at: *condition, eip: None };
|
||||
DisplayFork { name: fork.name().to_string(), activated_at: condition, eip: None };
|
||||
|
||||
match condition {
|
||||
ForkCondition::Block(_) => {
|
||||
pre_merge.push(display_fork);
|
||||
}
|
||||
ForkCondition::TTD { total_difficulty, .. } => {
|
||||
display_fork.activated_at = ForkCondition::TTD {
|
||||
fork_block: known_paris_block,
|
||||
total_difficulty: *total_difficulty,
|
||||
};
|
||||
display_fork.activated_at =
|
||||
ForkCondition::TTD { fork_block: known_paris_block, total_difficulty };
|
||||
with_merge.push(display_fork);
|
||||
}
|
||||
ForkCondition::Timestamp(_) => {
|
||||
|
||||
@ -1,702 +0,0 @@
|
||||
use alloy_chains::Chain;
|
||||
use core::{
|
||||
fmt,
|
||||
fmt::{Display, Formatter},
|
||||
str::FromStr,
|
||||
};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::{format, string::String};
|
||||
|
||||
/// Represents the consensus type of a blockchain fork.
|
||||
///
|
||||
/// This enum defines two variants: `ProofOfWork` for hardforks that use a proof-of-work consensus
|
||||
/// mechanism, and `ProofOfStake` for hardforks that use a proof-of-stake consensus mechanism.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub enum ConsensusType {
|
||||
/// Indicates a proof-of-work consensus mechanism.
|
||||
ProofOfWork,
|
||||
/// Indicates a proof-of-stake consensus mechanism.
|
||||
ProofOfStake,
|
||||
}
|
||||
|
||||
/// The name of an Ethereum hardfork.
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
#[non_exhaustive]
|
||||
pub enum Hardfork {
|
||||
/// Frontier: <https://blog.ethereum.org/2015/03/03/ethereum-launch-process>.
|
||||
Frontier,
|
||||
/// Homestead: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md>.
|
||||
Homestead,
|
||||
/// The DAO fork: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md>.
|
||||
Dao,
|
||||
/// Tangerine: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md>.
|
||||
Tangerine,
|
||||
/// Spurious Dragon: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md>.
|
||||
SpuriousDragon,
|
||||
/// Byzantium: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md>.
|
||||
Byzantium,
|
||||
/// Constantinople: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md>.
|
||||
Constantinople,
|
||||
/// Petersburg: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md>.
|
||||
Petersburg,
|
||||
/// Istanbul: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md>.
|
||||
Istanbul,
|
||||
/// Muir Glacier: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md>.
|
||||
MuirGlacier,
|
||||
/// Berlin: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md>.
|
||||
Berlin,
|
||||
/// London: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md>.
|
||||
London,
|
||||
/// Arrow Glacier: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md>.
|
||||
ArrowGlacier,
|
||||
/// Gray Glacier: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md>.
|
||||
GrayGlacier,
|
||||
/// Paris: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md>.
|
||||
Paris,
|
||||
/// Bedrock: <https://blog.oplabs.co/introducing-optimism-bedrock>.
|
||||
#[cfg(feature = "optimism")]
|
||||
Bedrock,
|
||||
/// Regolith: <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#regolith>.
|
||||
#[cfg(feature = "optimism")]
|
||||
Regolith,
|
||||
/// Shanghai: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md>.
|
||||
Shanghai,
|
||||
/// Canyon:
|
||||
/// <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#canyon>.
|
||||
#[cfg(feature = "optimism")]
|
||||
Canyon,
|
||||
// ArbOS11,
|
||||
/// Cancun.
|
||||
Cancun,
|
||||
/// Ecotone: <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#ecotone>.
|
||||
#[cfg(feature = "optimism")]
|
||||
Ecotone,
|
||||
// ArbOS20Atlas,
|
||||
|
||||
// Upcoming
|
||||
/// Prague: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/prague.md>
|
||||
Prague,
|
||||
/// Fjord: <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#fjord>
|
||||
#[cfg(feature = "optimism")]
|
||||
Fjord,
|
||||
}
|
||||
|
||||
impl Hardfork {
|
||||
/// Retrieves the consensus type for the specified hardfork.
|
||||
pub fn consensus_type(&self) -> ConsensusType {
|
||||
if *self >= Self::Paris {
|
||||
ConsensusType::ProofOfStake
|
||||
} else {
|
||||
ConsensusType::ProofOfWork
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if the hardfork uses Proof of Stake consensus.
|
||||
pub fn is_proof_of_stake(&self) -> bool {
|
||||
matches!(self.consensus_type(), ConsensusType::ProofOfStake)
|
||||
}
|
||||
|
||||
/// Checks if the hardfork uses Proof of Work consensus.
|
||||
pub fn is_proof_of_work(&self) -> bool {
|
||||
matches!(self.consensus_type(), ConsensusType::ProofOfWork)
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the given chain.
|
||||
pub fn activation_block(&self, chain: Chain) -> Option<u64> {
|
||||
if chain == Chain::mainnet() {
|
||||
return self.mainnet_activation_block()
|
||||
}
|
||||
if chain == Chain::sepolia() {
|
||||
return self.sepolia_activation_block()
|
||||
}
|
||||
if chain == Chain::holesky() {
|
||||
return self.holesky_activation_block()
|
||||
}
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
{
|
||||
if chain == Chain::base_sepolia() {
|
||||
return self.base_sepolia_activation_block()
|
||||
}
|
||||
if chain == Chain::base_mainnet() {
|
||||
return self.base_mainnet_activation_block()
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Ethereum mainnet.
|
||||
pub const fn mainnet_activation_block(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier => Some(0),
|
||||
Self::Homestead => Some(1150000),
|
||||
Self::Dao => Some(1920000),
|
||||
Self::Tangerine => Some(2463000),
|
||||
Self::SpuriousDragon => Some(2675000),
|
||||
Self::Byzantium => Some(4370000),
|
||||
Self::Constantinople | Self::Petersburg => Some(7280000),
|
||||
Self::Istanbul => Some(9069000),
|
||||
Self::MuirGlacier => Some(9200000),
|
||||
Self::Berlin => Some(12244000),
|
||||
Self::London => Some(12965000),
|
||||
Self::ArrowGlacier => Some(13773000),
|
||||
Self::GrayGlacier => Some(15050000),
|
||||
Self::Paris => Some(15537394),
|
||||
Self::Shanghai => Some(17034870),
|
||||
Self::Cancun => Some(19426587),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Sepolia testnet.
|
||||
pub const fn sepolia_activation_block(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Paris => Some(1735371),
|
||||
Self::Shanghai => Some(2990908),
|
||||
Self::Cancun => Some(5187023),
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier => Some(0),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Arbitrum Sepolia testnet.
|
||||
pub const fn arbitrum_sepolia_activation_block(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(0),
|
||||
Self::Shanghai => Some(10653737),
|
||||
// Hardfork::ArbOS11 => Some(10653737),
|
||||
Self::Cancun => Some(18683405),
|
||||
// Hardfork::ArbOS20Atlas => Some(18683405),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Arbitrum One mainnet.
|
||||
pub const fn arbitrum_activation_block(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(0),
|
||||
Self::Shanghai => Some(184097479),
|
||||
// Hardfork::ArbOS11 => Some(184097479),
|
||||
Self::Cancun => Some(190301729),
|
||||
// Hardfork::ArbOS20Atlas => Some(190301729),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Base Sepolia testnet.
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const fn base_sepolia_activation_block(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris |
|
||||
Self::Bedrock |
|
||||
Self::Regolith => Some(0),
|
||||
Self::Shanghai | Self::Canyon => Some(2106456),
|
||||
Self::Cancun | Self::Ecotone => Some(6383256),
|
||||
Self::Fjord => Some(10615056),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Base mainnet.
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const fn base_mainnet_activation_block(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris |
|
||||
Self::Bedrock |
|
||||
Self::Regolith => Some(0),
|
||||
Self::Shanghai | Self::Canyon => Some(9101527),
|
||||
Self::Cancun | Self::Ecotone => Some(11188936),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the holesky testnet.
|
||||
const fn holesky_activation_block(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(0),
|
||||
Self::Shanghai => Some(6698),
|
||||
Self::Cancun => Some(894733),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the given chain.
|
||||
pub fn activation_timestamp(&self, chain: Chain) -> Option<u64> {
|
||||
if chain == Chain::mainnet() {
|
||||
return self.mainnet_activation_timestamp()
|
||||
}
|
||||
if chain == Chain::sepolia() {
|
||||
return self.sepolia_activation_timestamp()
|
||||
}
|
||||
if chain == Chain::holesky() {
|
||||
return self.holesky_activation_timestamp()
|
||||
}
|
||||
#[cfg(feature = "optimism")]
|
||||
{
|
||||
if chain == Chain::base_sepolia() {
|
||||
return self.base_sepolia_activation_timestamp()
|
||||
}
|
||||
if chain == Chain::base_mainnet() {
|
||||
return self.base_mainnet_activation_timestamp()
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Ethereum mainnet.
|
||||
pub const fn mainnet_activation_timestamp(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier => Some(1438226773),
|
||||
Self::Homestead => Some(1457938193),
|
||||
Self::Dao => Some(1468977640),
|
||||
Self::Tangerine => Some(1476753571),
|
||||
Self::SpuriousDragon => Some(1479788144),
|
||||
Self::Byzantium => Some(1508131331),
|
||||
Self::Constantinople | Self::Petersburg => Some(1551340324),
|
||||
Self::Istanbul => Some(1575807909),
|
||||
Self::MuirGlacier => Some(1577953849),
|
||||
Self::Berlin => Some(1618481223),
|
||||
Self::London => Some(1628166822),
|
||||
Self::ArrowGlacier => Some(1639036523),
|
||||
Self::GrayGlacier => Some(1656586444),
|
||||
Self::Paris => Some(1663224162),
|
||||
Self::Shanghai => Some(1681338455),
|
||||
Self::Cancun => Some(1710338135),
|
||||
|
||||
// upcoming hardforks
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Sepolia testnet.
|
||||
pub const fn sepolia_activation_timestamp(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(1633267481),
|
||||
Self::Shanghai => Some(1677557088),
|
||||
Self::Cancun => Some(1706655072),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Holesky testnet.
|
||||
pub const fn holesky_activation_timestamp(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Shanghai => Some(1696000704),
|
||||
Self::Cancun => Some(1707305664),
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(1695902100),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Arbitrum Sepolia
|
||||
/// testnet.
|
||||
pub const fn arbitrum_sepolia_activation_timestamp(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(1692726996),
|
||||
Self::Shanghai => Some(1706634000),
|
||||
// Hardfork::ArbOS11 => Some(1706634000),
|
||||
Self::Cancun => Some(1709229600),
|
||||
// Hardfork::ArbOS20Atlas => Some(1709229600),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Arbitrum One mainnet.
|
||||
pub const fn arbitrum_activation_timestamp(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(1622240000),
|
||||
Self::Shanghai => Some(1708804873),
|
||||
// Hardfork::ArbOS11 => Some(1708804873),
|
||||
Self::Cancun => Some(1710424089),
|
||||
// Hardfork::ArbOS20Atlas => Some(1710424089),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Base Sepolia testnet.
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const fn base_sepolia_activation_timestamp(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris |
|
||||
Self::Bedrock |
|
||||
Self::Regolith => Some(1695768288),
|
||||
Self::Shanghai | Self::Canyon => Some(1699981200),
|
||||
Self::Cancun | Self::Ecotone => Some(1708534800),
|
||||
Self::Fjord => Some(1716998400),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Base mainnet.
|
||||
#[cfg(feature = "optimism")]
|
||||
pub const fn base_mainnet_activation_timestamp(&self) -> Option<u64> {
|
||||
#[allow(unreachable_patterns)]
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris |
|
||||
Self::Bedrock |
|
||||
Self::Regolith => Some(1686789347),
|
||||
Self::Shanghai | Self::Canyon => Some(1704992401),
|
||||
Self::Cancun | Self::Ecotone => Some(1710374401),
|
||||
Self::Fjord => Some(1720627201),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Hardfork {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s.to_lowercase().as_str() {
|
||||
"frontier" => Self::Frontier,
|
||||
"homestead" => Self::Homestead,
|
||||
"dao" => Self::Dao,
|
||||
"tangerine" => Self::Tangerine,
|
||||
"spuriousdragon" => Self::SpuriousDragon,
|
||||
"byzantium" => Self::Byzantium,
|
||||
"constantinople" => Self::Constantinople,
|
||||
"petersburg" => Self::Petersburg,
|
||||
"istanbul" => Self::Istanbul,
|
||||
"muirglacier" => Self::MuirGlacier,
|
||||
"berlin" => Self::Berlin,
|
||||
"london" => Self::London,
|
||||
"arrowglacier" => Self::ArrowGlacier,
|
||||
"grayglacier" => Self::GrayGlacier,
|
||||
"paris" => Self::Paris,
|
||||
"shanghai" => Self::Shanghai,
|
||||
"cancun" => Self::Cancun,
|
||||
#[cfg(feature = "optimism")]
|
||||
"bedrock" => Self::Bedrock,
|
||||
#[cfg(feature = "optimism")]
|
||||
"regolith" => Self::Regolith,
|
||||
#[cfg(feature = "optimism")]
|
||||
"canyon" => Self::Canyon,
|
||||
#[cfg(feature = "optimism")]
|
||||
"ecotone" => Self::Ecotone,
|
||||
#[cfg(feature = "optimism")]
|
||||
"fjord" => Self::Fjord,
|
||||
"prague" => Self::Prague,
|
||||
// "arbos11" => Hardfork::ArbOS11,
|
||||
// "arbos20atlas" => Hardfork::ArbOS20Atlas,
|
||||
_ => return Err(format!("Unknown hardfork: {s}")),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Hardfork {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{self:?}")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn check_hardfork_from_str() {
|
||||
let hardfork_str = [
|
||||
"frOntier",
|
||||
"homEstead",
|
||||
"dao",
|
||||
"tAngerIne",
|
||||
"spurIousdrAgon",
|
||||
"byzAntium",
|
||||
"constantinople",
|
||||
"petersburg",
|
||||
"istanbul",
|
||||
"muirglacier",
|
||||
"bErlin",
|
||||
"lonDon",
|
||||
"arrowglacier",
|
||||
"grayglacier",
|
||||
"PARIS",
|
||||
"ShAnGhAI",
|
||||
"CaNcUn",
|
||||
"PrAguE",
|
||||
];
|
||||
let expected_hardforks = [
|
||||
Hardfork::Frontier,
|
||||
Hardfork::Homestead,
|
||||
Hardfork::Dao,
|
||||
Hardfork::Tangerine,
|
||||
Hardfork::SpuriousDragon,
|
||||
Hardfork::Byzantium,
|
||||
Hardfork::Constantinople,
|
||||
Hardfork::Petersburg,
|
||||
Hardfork::Istanbul,
|
||||
Hardfork::MuirGlacier,
|
||||
Hardfork::Berlin,
|
||||
Hardfork::London,
|
||||
Hardfork::ArrowGlacier,
|
||||
Hardfork::GrayGlacier,
|
||||
Hardfork::Paris,
|
||||
Hardfork::Shanghai,
|
||||
Hardfork::Cancun,
|
||||
Hardfork::Prague,
|
||||
];
|
||||
|
||||
let hardforks: Vec<Hardfork> =
|
||||
hardfork_str.iter().map(|h| Hardfork::from_str(h).unwrap()).collect();
|
||||
|
||||
assert_eq!(hardforks, expected_hardforks);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "optimism")]
|
||||
fn check_op_hardfork_from_str() {
|
||||
let hardfork_str = ["beDrOck", "rEgOlITH", "cAnYoN", "eCoToNe", "FJorD"];
|
||||
let expected_hardforks = [
|
||||
Hardfork::Bedrock,
|
||||
Hardfork::Regolith,
|
||||
Hardfork::Canyon,
|
||||
Hardfork::Ecotone,
|
||||
Hardfork::Fjord,
|
||||
];
|
||||
|
||||
let hardforks: Vec<Hardfork> =
|
||||
hardfork_str.iter().map(|h| Hardfork::from_str(h).unwrap()).collect();
|
||||
|
||||
assert_eq!(hardforks, expected_hardforks);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_nonexistent_hardfork_from_str() {
|
||||
assert!(Hardfork::from_str("not a hardfork").is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_consensus_type() {
|
||||
let pow_hardforks = [
|
||||
Hardfork::Frontier,
|
||||
Hardfork::Homestead,
|
||||
Hardfork::Dao,
|
||||
Hardfork::Tangerine,
|
||||
Hardfork::SpuriousDragon,
|
||||
Hardfork::Byzantium,
|
||||
Hardfork::Constantinople,
|
||||
Hardfork::Petersburg,
|
||||
Hardfork::Istanbul,
|
||||
Hardfork::MuirGlacier,
|
||||
Hardfork::Berlin,
|
||||
Hardfork::London,
|
||||
Hardfork::ArrowGlacier,
|
||||
Hardfork::GrayGlacier,
|
||||
];
|
||||
|
||||
let pos_hardforks = [Hardfork::Paris, Hardfork::Shanghai, Hardfork::Cancun];
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
let op_hardforks = [
|
||||
Hardfork::Bedrock,
|
||||
Hardfork::Regolith,
|
||||
Hardfork::Canyon,
|
||||
Hardfork::Ecotone,
|
||||
Hardfork::Fjord,
|
||||
];
|
||||
|
||||
for hardfork in &pow_hardforks {
|
||||
assert_eq!(hardfork.consensus_type(), ConsensusType::ProofOfWork);
|
||||
assert!(!hardfork.is_proof_of_stake());
|
||||
assert!(hardfork.is_proof_of_work());
|
||||
}
|
||||
|
||||
for hardfork in &pos_hardforks {
|
||||
assert_eq!(hardfork.consensus_type(), ConsensusType::ProofOfStake);
|
||||
assert!(hardfork.is_proof_of_stake());
|
||||
assert!(!hardfork.is_proof_of_work());
|
||||
}
|
||||
|
||||
#[cfg(feature = "optimism")]
|
||||
for hardfork in &op_hardforks {
|
||||
assert_eq!(hardfork.consensus_type(), ConsensusType::ProofOfStake);
|
||||
assert!(hardfork.is_proof_of_stake());
|
||||
assert!(!hardfork.is_proof_of_work());
|
||||
}
|
||||
}
|
||||
}
|
||||
32
crates/ethereum-forks/src/hardfork/dev.rs
Normal file
32
crates/ethereum-forks/src/hardfork/dev.rs
Normal file
@ -0,0 +1,32 @@
|
||||
use crate::{ChainHardforks, EthereumHardfork, ForkCondition};
|
||||
use alloy_primitives::U256;
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
/// Dev hardforks
|
||||
pub static DEV_HARDFORKS: Lazy<ChainHardforks> = Lazy::new(|| {
|
||||
ChainHardforks::new(vec![
|
||||
(EthereumHardfork::Frontier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Homestead.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Dao.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Tangerine.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::SpuriousDragon.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Byzantium.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Constantinople.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Petersburg.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Istanbul.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Berlin.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::London.boxed(), ForkCondition::Block(0)),
|
||||
(
|
||||
EthereumHardfork::Paris.boxed(),
|
||||
ForkCondition::TTD { fork_block: None, total_difficulty: U256::ZERO },
|
||||
),
|
||||
(EthereumHardfork::Shanghai.boxed(), ForkCondition::Timestamp(0)),
|
||||
(EthereumHardfork::Cancun.boxed(), ForkCondition::Timestamp(0)),
|
||||
#[cfg(feature = "optimism")]
|
||||
(crate::OptimismHardfork::Regolith.boxed(), ForkCondition::Timestamp(0)),
|
||||
#[cfg(feature = "optimism")]
|
||||
(crate::OptimismHardfork::Bedrock.boxed(), ForkCondition::Block(0)),
|
||||
#[cfg(feature = "optimism")]
|
||||
(crate::OptimismHardfork::Ecotone.boxed(), ForkCondition::Timestamp(0)),
|
||||
])
|
||||
});
|
||||
441
crates/ethereum-forks/src/hardfork/ethereum.rs
Normal file
441
crates/ethereum-forks/src/hardfork/ethereum.rs
Normal file
@ -0,0 +1,441 @@
|
||||
use crate::{hardfork, ChainHardforks, ForkCondition, Hardfork};
|
||||
use alloy_chains::Chain;
|
||||
use alloy_primitives::{uint, U256};
|
||||
use core::{
|
||||
fmt,
|
||||
fmt::{Display, Formatter},
|
||||
str::FromStr,
|
||||
};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
hardfork!(
|
||||
/// The name of an Ethereum hardfork.
|
||||
EthereumHardfork {
|
||||
/// Frontier: <https://blog.ethereum.org/2015/03/03/ethereum-launch-process>.
|
||||
Frontier,
|
||||
/// Homestead: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/homestead.md>.
|
||||
Homestead,
|
||||
/// The DAO fork: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/dao-fork.md>.
|
||||
Dao,
|
||||
/// Tangerine: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/tangerine-whistle.md>.
|
||||
Tangerine,
|
||||
/// Spurious Dragon: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/spurious-dragon.md>.
|
||||
SpuriousDragon,
|
||||
/// Byzantium: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/byzantium.md>.
|
||||
Byzantium,
|
||||
/// Constantinople: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/constantinople.md>.
|
||||
Constantinople,
|
||||
/// Petersburg: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/petersburg.md>.
|
||||
Petersburg,
|
||||
/// Istanbul: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/istanbul.md>.
|
||||
Istanbul,
|
||||
/// Muir Glacier: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/muir-glacier.md>.
|
||||
MuirGlacier,
|
||||
/// Berlin: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/berlin.md>.
|
||||
Berlin,
|
||||
/// London: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/london.md>.
|
||||
London,
|
||||
/// Arrow Glacier: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/arrow-glacier.md>.
|
||||
ArrowGlacier,
|
||||
/// Gray Glacier: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/gray-glacier.md>.
|
||||
GrayGlacier,
|
||||
/// Paris: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/paris.md>.
|
||||
Paris,
|
||||
/// Shanghai: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/shanghai.md>.
|
||||
Shanghai,
|
||||
/// Cancun.
|
||||
Cancun,
|
||||
/// Prague: <https://github.com/ethereum/execution-specs/blob/master/network-upgrades/mainnet-upgrades/prague.md>
|
||||
Prague,
|
||||
}
|
||||
);
|
||||
|
||||
impl EthereumHardfork {
|
||||
/// Retrieves the activation block for the specified hardfork on the given chain.
|
||||
pub fn activation_block(&self, chain: Chain) -> Option<u64> {
|
||||
if chain == Chain::mainnet() {
|
||||
return self.mainnet_activation_block()
|
||||
}
|
||||
if chain == Chain::sepolia() {
|
||||
return self.sepolia_activation_block()
|
||||
}
|
||||
if chain == Chain::holesky() {
|
||||
return self.holesky_activation_block()
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Ethereum mainnet.
|
||||
pub const fn mainnet_activation_block(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Frontier => Some(0),
|
||||
Self::Homestead => Some(1150000),
|
||||
Self::Dao => Some(1920000),
|
||||
Self::Tangerine => Some(2463000),
|
||||
Self::SpuriousDragon => Some(2675000),
|
||||
Self::Byzantium => Some(4370000),
|
||||
Self::Constantinople | Self::Petersburg => Some(7280000),
|
||||
Self::Istanbul => Some(9069000),
|
||||
Self::MuirGlacier => Some(9200000),
|
||||
Self::Berlin => Some(12244000),
|
||||
Self::London => Some(12965000),
|
||||
Self::ArrowGlacier => Some(13773000),
|
||||
Self::GrayGlacier => Some(15050000),
|
||||
Self::Paris => Some(15537394),
|
||||
Self::Shanghai => Some(17034870),
|
||||
Self::Cancun => Some(19426587),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Sepolia testnet.
|
||||
pub const fn sepolia_activation_block(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Paris => Some(1735371),
|
||||
Self::Shanghai => Some(2990908),
|
||||
Self::Cancun => Some(5187023),
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier => Some(0),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the holesky testnet.
|
||||
const fn holesky_activation_block(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(0),
|
||||
Self::Shanghai => Some(6698),
|
||||
Self::Cancun => Some(894733),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Arbitrum Sepolia testnet.
|
||||
pub const fn arbitrum_sepolia_activation_block(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(0),
|
||||
Self::Shanghai => Some(10653737),
|
||||
// Hardfork::ArbOS11 => Some(10653737),
|
||||
Self::Cancun => Some(18683405),
|
||||
// Hardfork::ArbOS20Atlas => Some(18683405),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Arbitrum One mainnet.
|
||||
pub const fn arbitrum_activation_block(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(0),
|
||||
Self::Shanghai => Some(184097479),
|
||||
// Hardfork::ArbOS11 => Some(184097479),
|
||||
Self::Cancun => Some(190301729),
|
||||
// Hardfork::ArbOS20Atlas => Some(190301729),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the given chain.
|
||||
pub fn activation_timestamp(&self, chain: Chain) -> Option<u64> {
|
||||
if chain == Chain::mainnet() {
|
||||
return self.mainnet_activation_timestamp()
|
||||
}
|
||||
if chain == Chain::sepolia() {
|
||||
return self.sepolia_activation_timestamp()
|
||||
}
|
||||
if chain == Chain::holesky() {
|
||||
return self.holesky_activation_timestamp()
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Ethereum mainnet.
|
||||
pub const fn mainnet_activation_timestamp(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Frontier => Some(1438226773),
|
||||
Self::Homestead => Some(1457938193),
|
||||
Self::Dao => Some(1468977640),
|
||||
Self::Tangerine => Some(1476753571),
|
||||
Self::SpuriousDragon => Some(1479788144),
|
||||
Self::Byzantium => Some(1508131331),
|
||||
Self::Constantinople | Self::Petersburg => Some(1551340324),
|
||||
Self::Istanbul => Some(1575807909),
|
||||
Self::MuirGlacier => Some(1577953849),
|
||||
Self::Berlin => Some(1618481223),
|
||||
Self::London => Some(1628166822),
|
||||
Self::ArrowGlacier => Some(1639036523),
|
||||
Self::GrayGlacier => Some(1656586444),
|
||||
Self::Paris => Some(1663224162),
|
||||
Self::Shanghai => Some(1681338455),
|
||||
Self::Cancun => Some(1710338135),
|
||||
|
||||
// upcoming hardforks
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Sepolia testnet.
|
||||
pub const fn sepolia_activation_timestamp(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(1633267481),
|
||||
Self::Shanghai => Some(1677557088),
|
||||
Self::Cancun => Some(1706655072),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Holesky testnet.
|
||||
pub const fn holesky_activation_timestamp(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Shanghai => Some(1696000704),
|
||||
Self::Cancun => Some(1707305664),
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(1695902100),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Arbitrum Sepolia
|
||||
/// testnet.
|
||||
pub const fn arbitrum_sepolia_activation_timestamp(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(1692726996),
|
||||
Self::Shanghai => Some(1706634000),
|
||||
// Hardfork::ArbOS11 => Some(1706634000),
|
||||
Self::Cancun => Some(1709229600),
|
||||
// Hardfork::ArbOS20Atlas => Some(1709229600),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Arbitrum One mainnet.
|
||||
pub const fn arbitrum_activation_timestamp(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Frontier |
|
||||
Self::Homestead |
|
||||
Self::Dao |
|
||||
Self::Tangerine |
|
||||
Self::SpuriousDragon |
|
||||
Self::Byzantium |
|
||||
Self::Constantinople |
|
||||
Self::Petersburg |
|
||||
Self::Istanbul |
|
||||
Self::MuirGlacier |
|
||||
Self::Berlin |
|
||||
Self::London |
|
||||
Self::ArrowGlacier |
|
||||
Self::GrayGlacier |
|
||||
Self::Paris => Some(1622240000),
|
||||
Self::Shanghai => Some(1708804873),
|
||||
// Hardfork::ArbOS11 => Some(1708804873),
|
||||
Self::Cancun => Some(1710424089),
|
||||
// Hardfork::ArbOS20Atlas => Some(1710424089),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Ethereum mainnet list of hardforks.
|
||||
pub const fn mainnet() -> [(Self, ForkCondition); 17] {
|
||||
[
|
||||
(Self::Frontier, ForkCondition::Block(0)),
|
||||
(Self::Homestead, ForkCondition::Block(1150000)),
|
||||
(Self::Dao, ForkCondition::Block(1920000)),
|
||||
(Self::Tangerine, ForkCondition::Block(2463000)),
|
||||
(Self::SpuriousDragon, ForkCondition::Block(2675000)),
|
||||
(Self::Byzantium, ForkCondition::Block(4370000)),
|
||||
(Self::Constantinople, ForkCondition::Block(7280000)),
|
||||
(Self::Petersburg, ForkCondition::Block(7280000)),
|
||||
(Self::Istanbul, ForkCondition::Block(9069000)),
|
||||
(Self::MuirGlacier, ForkCondition::Block(9200000)),
|
||||
(Self::Berlin, ForkCondition::Block(12244000)),
|
||||
(Self::London, ForkCondition::Block(12965000)),
|
||||
(Self::ArrowGlacier, ForkCondition::Block(13773000)),
|
||||
(Self::GrayGlacier, ForkCondition::Block(15050000)),
|
||||
(
|
||||
Self::Paris,
|
||||
ForkCondition::TTD {
|
||||
fork_block: None,
|
||||
total_difficulty: uint!(58_750_000_000_000_000_000_000_U256),
|
||||
},
|
||||
),
|
||||
(Self::Shanghai, ForkCondition::Timestamp(1681338455)),
|
||||
(Self::Cancun, ForkCondition::Timestamp(1710338135)),
|
||||
]
|
||||
}
|
||||
|
||||
/// Ethereum goerli list of hardforks.
|
||||
pub const fn goerli() -> [(Self, ForkCondition); 14] {
|
||||
[
|
||||
(Self::Frontier, ForkCondition::Block(0)),
|
||||
(Self::Homestead, ForkCondition::Block(0)),
|
||||
(Self::Dao, ForkCondition::Block(0)),
|
||||
(Self::Tangerine, ForkCondition::Block(0)),
|
||||
(Self::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Self::Byzantium, ForkCondition::Block(0)),
|
||||
(Self::Constantinople, ForkCondition::Block(0)),
|
||||
(Self::Petersburg, ForkCondition::Block(0)),
|
||||
(Self::Istanbul, ForkCondition::Block(1561651)),
|
||||
(Self::Berlin, ForkCondition::Block(4460644)),
|
||||
(Self::London, ForkCondition::Block(5062605)),
|
||||
(
|
||||
Self::Paris,
|
||||
ForkCondition::TTD { fork_block: None, total_difficulty: uint!(10_790_000_U256) },
|
||||
),
|
||||
(Self::Shanghai, ForkCondition::Timestamp(1678832736)),
|
||||
(Self::Cancun, ForkCondition::Timestamp(1705473120)),
|
||||
]
|
||||
}
|
||||
|
||||
/// Ethereum sepolia list of hardforks.
|
||||
pub const fn sepolia() -> [(Self, ForkCondition); 15] {
|
||||
[
|
||||
(Self::Frontier, ForkCondition::Block(0)),
|
||||
(Self::Homestead, ForkCondition::Block(0)),
|
||||
(Self::Dao, ForkCondition::Block(0)),
|
||||
(Self::Tangerine, ForkCondition::Block(0)),
|
||||
(Self::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Self::Byzantium, ForkCondition::Block(0)),
|
||||
(Self::Constantinople, ForkCondition::Block(0)),
|
||||
(Self::Petersburg, ForkCondition::Block(0)),
|
||||
(Self::Istanbul, ForkCondition::Block(0)),
|
||||
(Self::MuirGlacier, ForkCondition::Block(0)),
|
||||
(Self::Berlin, ForkCondition::Block(0)),
|
||||
(Self::London, ForkCondition::Block(0)),
|
||||
(
|
||||
Self::Paris,
|
||||
ForkCondition::TTD {
|
||||
fork_block: Some(1735371),
|
||||
total_difficulty: uint!(17_000_000_000_000_000_U256),
|
||||
},
|
||||
),
|
||||
(Self::Shanghai, ForkCondition::Timestamp(1677557088)),
|
||||
(Self::Cancun, ForkCondition::Timestamp(1706655072)),
|
||||
]
|
||||
}
|
||||
|
||||
/// Ethereum holesky list of hardforks.
|
||||
pub const fn holesky() -> [(Self, ForkCondition); 15] {
|
||||
[
|
||||
(Self::Frontier, ForkCondition::Block(0)),
|
||||
(Self::Homestead, ForkCondition::Block(0)),
|
||||
(Self::Dao, ForkCondition::Block(0)),
|
||||
(Self::Tangerine, ForkCondition::Block(0)),
|
||||
(Self::SpuriousDragon, ForkCondition::Block(0)),
|
||||
(Self::Byzantium, ForkCondition::Block(0)),
|
||||
(Self::Constantinople, ForkCondition::Block(0)),
|
||||
(Self::Petersburg, ForkCondition::Block(0)),
|
||||
(Self::Istanbul, ForkCondition::Block(0)),
|
||||
(Self::MuirGlacier, ForkCondition::Block(0)),
|
||||
(Self::Berlin, ForkCondition::Block(0)),
|
||||
(Self::London, ForkCondition::Block(0)),
|
||||
(Self::Paris, ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO }),
|
||||
(Self::Shanghai, ForkCondition::Timestamp(1696000704)),
|
||||
(Self::Cancun, ForkCondition::Timestamp(1707305664)),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<[(EthereumHardfork, ForkCondition); N]> for ChainHardforks {
|
||||
fn from(list: [(EthereumHardfork, ForkCondition); N]) -> Self {
|
||||
Self::new(
|
||||
list.into_iter()
|
||||
.map(|(fork, cond)| (Box::new(fork) as Box<dyn Hardfork>, cond))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
52
crates/ethereum-forks/src/hardfork/macros.rs
Normal file
52
crates/ethereum-forks/src/hardfork/macros.rs
Normal file
@ -0,0 +1,52 @@
|
||||
/// Macro that defines different variants of a chain specific enum. See [`crate::Hardfork`] as an
|
||||
/// example.
|
||||
#[macro_export]
|
||||
macro_rules! hardfork {
|
||||
($(#[$enum_meta:meta])* $enum:ident { $( $(#[$meta:meta])* $variant:ident ),* $(,)? }) => {
|
||||
$(#[$enum_meta])*
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
|
||||
pub enum $enum {
|
||||
$( $(#[$meta])* $variant ),*
|
||||
}
|
||||
|
||||
impl $enum {
|
||||
/// Returns variant as `str`.
|
||||
pub const fn name(&self) -> &'static str {
|
||||
match self {
|
||||
$( $enum::$variant => stringify!($variant), )*
|
||||
}
|
||||
}
|
||||
|
||||
/// Boxes `self` and returns it as `Box<dyn Hardfork>`.
|
||||
pub fn boxed(self) -> Box<dyn Hardfork> {
|
||||
Box::new(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for $enum {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.to_lowercase().as_str() {
|
||||
$(
|
||||
s if s == stringify!($variant).to_lowercase() => Ok($enum::$variant),
|
||||
)*
|
||||
_ => return Err(format!("Unknown hardfork: {s}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Hardfork for $enum {
|
||||
fn name(&self) -> &'static str {
|
||||
self.name()
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for $enum {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{self:?}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
126
crates/ethereum-forks/src/hardfork/mod.rs
Normal file
126
crates/ethereum-forks/src/hardfork/mod.rs
Normal file
@ -0,0 +1,126 @@
|
||||
mod macros;
|
||||
|
||||
mod ethereum;
|
||||
pub use ethereum::EthereumHardfork;
|
||||
|
||||
mod optimism;
|
||||
pub use optimism::OptimismHardfork;
|
||||
|
||||
mod dev;
|
||||
pub use dev::DEV_HARDFORKS;
|
||||
|
||||
use core::{
|
||||
any::Any,
|
||||
hash::{Hash, Hasher},
|
||||
};
|
||||
use dyn_clone::DynClone;
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::{format, string::String};
|
||||
|
||||
/// Generic hardfork trait.
|
||||
#[auto_impl::auto_impl(&, Box)]
|
||||
pub trait Hardfork: Any + DynClone + Send + Sync + 'static {
|
||||
/// Fork name.
|
||||
fn name(&self) -> &'static str;
|
||||
}
|
||||
|
||||
dyn_clone::clone_trait_object!(Hardfork);
|
||||
|
||||
impl core::fmt::Debug for dyn Hardfork + 'static {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct(self.name()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for dyn Hardfork + 'static {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.name() == other.name()
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for dyn Hardfork + 'static {}
|
||||
|
||||
impl Hash for dyn Hardfork + 'static {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.name().hash(state)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::hardfork::optimism::OptimismHardfork;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn check_hardfork_from_str() {
|
||||
let hardfork_str = [
|
||||
"frOntier",
|
||||
"homEstead",
|
||||
"dao",
|
||||
"tAngerIne",
|
||||
"spurIousdrAgon",
|
||||
"byzAntium",
|
||||
"constantinople",
|
||||
"petersburg",
|
||||
"istanbul",
|
||||
"muirglacier",
|
||||
"bErlin",
|
||||
"lonDon",
|
||||
"arrowglacier",
|
||||
"grayglacier",
|
||||
"PARIS",
|
||||
"ShAnGhAI",
|
||||
"CaNcUn",
|
||||
"PrAguE",
|
||||
];
|
||||
let expected_hardforks = [
|
||||
EthereumHardfork::Frontier,
|
||||
EthereumHardfork::Homestead,
|
||||
EthereumHardfork::Dao,
|
||||
EthereumHardfork::Tangerine,
|
||||
EthereumHardfork::SpuriousDragon,
|
||||
EthereumHardfork::Byzantium,
|
||||
EthereumHardfork::Constantinople,
|
||||
EthereumHardfork::Petersburg,
|
||||
EthereumHardfork::Istanbul,
|
||||
EthereumHardfork::MuirGlacier,
|
||||
EthereumHardfork::Berlin,
|
||||
EthereumHardfork::London,
|
||||
EthereumHardfork::ArrowGlacier,
|
||||
EthereumHardfork::GrayGlacier,
|
||||
EthereumHardfork::Paris,
|
||||
EthereumHardfork::Shanghai,
|
||||
EthereumHardfork::Cancun,
|
||||
EthereumHardfork::Prague,
|
||||
];
|
||||
|
||||
let hardforks: Vec<EthereumHardfork> =
|
||||
hardfork_str.iter().map(|h| EthereumHardfork::from_str(h).unwrap()).collect();
|
||||
|
||||
assert_eq!(hardforks, expected_hardforks);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_op_hardfork_from_str() {
|
||||
let hardfork_str = ["beDrOck", "rEgOlITH", "cAnYoN", "eCoToNe", "FJorD"];
|
||||
let expected_hardforks = [
|
||||
OptimismHardfork::Bedrock,
|
||||
OptimismHardfork::Regolith,
|
||||
OptimismHardfork::Canyon,
|
||||
OptimismHardfork::Ecotone,
|
||||
OptimismHardfork::Fjord,
|
||||
];
|
||||
|
||||
let hardforks: Vec<OptimismHardfork> =
|
||||
hardfork_str.iter().map(|h| OptimismHardfork::from_str(h).unwrap()).collect();
|
||||
|
||||
assert_eq!(hardforks, expected_hardforks);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_nonexistent_hardfork_from_str() {
|
||||
assert!(EthereumHardfork::from_str("not a hardfork").is_err());
|
||||
}
|
||||
}
|
||||
337
crates/ethereum-forks/src/hardfork/optimism.rs
Normal file
337
crates/ethereum-forks/src/hardfork/optimism.rs
Normal file
@ -0,0 +1,337 @@
|
||||
use crate::{hardfork, ChainHardforks, EthereumHardfork, ForkCondition, Hardfork};
|
||||
use alloy_chains::Chain;
|
||||
use alloy_primitives::U256;
|
||||
use core::{
|
||||
any::Any,
|
||||
fmt::{self, Display, Formatter},
|
||||
str::FromStr,
|
||||
};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
hardfork!(
|
||||
/// The name of an optimism hardfork.
|
||||
///
|
||||
/// When building a list of hardforks for a chain, it's still expected to mix with [`EthereumHardfork`].
|
||||
OptimismHardfork {
|
||||
/// Bedrock: <https://blog.oplabs.co/introducing-optimism-bedrock>.
|
||||
Bedrock,
|
||||
/// Regolith: <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#regolith>.
|
||||
Regolith,
|
||||
/// <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#canyon>.
|
||||
Canyon,
|
||||
/// Ecotone: <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#ecotone>.
|
||||
Ecotone,
|
||||
/// Fjord: <https://github.com/ethereum-optimism/specs/blob/main/specs/protocol/superchain-upgrades.md#fjord>
|
||||
Fjord,
|
||||
}
|
||||
);
|
||||
|
||||
impl OptimismHardfork {
|
||||
/// Retrieves the activation block for the specified hardfork on the given chain.
|
||||
pub fn activation_block<H: Hardfork>(self, fork: H, chain: Chain) -> Option<u64> {
|
||||
if chain == Chain::base_sepolia() {
|
||||
return Self::base_sepolia_activation_block(fork)
|
||||
}
|
||||
if chain == Chain::base_mainnet() {
|
||||
return Self::base_mainnet_activation_block(fork)
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the given chain.
|
||||
pub fn activation_timestamp<H: Hardfork>(self, fork: H, chain: Chain) -> Option<u64> {
|
||||
if chain == Chain::base_sepolia() {
|
||||
return Self::base_sepolia_activation_timestamp(fork)
|
||||
}
|
||||
if chain == Chain::base_mainnet() {
|
||||
return Self::base_mainnet_activation_timestamp(fork)
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Base Sepolia testnet.
|
||||
pub fn base_sepolia_activation_block<H: Hardfork>(fork: H) -> Option<u64> {
|
||||
match_hardfork(
|
||||
fork,
|
||||
|fork| match fork {
|
||||
EthereumHardfork::Frontier |
|
||||
EthereumHardfork::Homestead |
|
||||
EthereumHardfork::Dao |
|
||||
EthereumHardfork::Tangerine |
|
||||
EthereumHardfork::SpuriousDragon |
|
||||
EthereumHardfork::Byzantium |
|
||||
EthereumHardfork::Constantinople |
|
||||
EthereumHardfork::Petersburg |
|
||||
EthereumHardfork::Istanbul |
|
||||
EthereumHardfork::MuirGlacier |
|
||||
EthereumHardfork::Berlin |
|
||||
EthereumHardfork::London |
|
||||
EthereumHardfork::ArrowGlacier |
|
||||
EthereumHardfork::GrayGlacier |
|
||||
EthereumHardfork::Paris |
|
||||
EthereumHardfork::Shanghai => Some(2106456),
|
||||
EthereumHardfork::Cancun => Some(6383256),
|
||||
_ => None,
|
||||
},
|
||||
|fork| match fork {
|
||||
Self::Bedrock | Self::Regolith => Some(0),
|
||||
Self::Canyon => Some(2106456),
|
||||
Self::Ecotone => Some(6383256),
|
||||
Self::Fjord => Some(10615056),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Retrieves the activation block for the specified hardfork on the Base mainnet.
|
||||
pub fn base_mainnet_activation_block<H: Hardfork>(fork: H) -> Option<u64> {
|
||||
match_hardfork(
|
||||
fork,
|
||||
|fork| match fork {
|
||||
EthereumHardfork::Frontier |
|
||||
EthereumHardfork::Homestead |
|
||||
EthereumHardfork::Dao |
|
||||
EthereumHardfork::Tangerine |
|
||||
EthereumHardfork::SpuriousDragon |
|
||||
EthereumHardfork::Byzantium |
|
||||
EthereumHardfork::Constantinople |
|
||||
EthereumHardfork::Petersburg |
|
||||
EthereumHardfork::Istanbul |
|
||||
EthereumHardfork::MuirGlacier |
|
||||
EthereumHardfork::Berlin |
|
||||
EthereumHardfork::London |
|
||||
EthereumHardfork::ArrowGlacier |
|
||||
EthereumHardfork::GrayGlacier |
|
||||
EthereumHardfork::Paris |
|
||||
EthereumHardfork::Shanghai => Some(9101527),
|
||||
EthereumHardfork::Cancun => Some(11188936),
|
||||
_ => None,
|
||||
},
|
||||
|fork| match fork {
|
||||
Self::Bedrock | Self::Regolith => Some(0),
|
||||
Self::Canyon => Some(9101527),
|
||||
Self::Ecotone => Some(11188936),
|
||||
_ => None,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Base Sepolia testnet.
|
||||
pub fn base_sepolia_activation_timestamp<H: Hardfork>(fork: H) -> Option<u64> {
|
||||
match_hardfork(
|
||||
fork,
|
||||
|fork| match fork {
|
||||
EthereumHardfork::Frontier |
|
||||
EthereumHardfork::Homestead |
|
||||
EthereumHardfork::Dao |
|
||||
EthereumHardfork::Tangerine |
|
||||
EthereumHardfork::SpuriousDragon |
|
||||
EthereumHardfork::Byzantium |
|
||||
EthereumHardfork::Constantinople |
|
||||
EthereumHardfork::Petersburg |
|
||||
EthereumHardfork::Istanbul |
|
||||
EthereumHardfork::MuirGlacier |
|
||||
EthereumHardfork::Berlin |
|
||||
EthereumHardfork::London |
|
||||
EthereumHardfork::ArrowGlacier |
|
||||
EthereumHardfork::GrayGlacier |
|
||||
EthereumHardfork::Paris |
|
||||
EthereumHardfork::Shanghai => Some(1699981200),
|
||||
EthereumHardfork::Cancun => Some(1708534800),
|
||||
_ => None,
|
||||
},
|
||||
|fork| match fork {
|
||||
Self::Bedrock | Self::Regolith => Some(1695768288),
|
||||
Self::Canyon => Some(1699981200),
|
||||
Self::Ecotone => Some(1708534800),
|
||||
Self::Fjord => Some(1716998400),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Retrieves the activation timestamp for the specified hardfork on the Base mainnet.
|
||||
pub fn base_mainnet_activation_timestamp<H: Hardfork>(fork: H) -> Option<u64> {
|
||||
match_hardfork(
|
||||
fork,
|
||||
|fork| match fork {
|
||||
EthereumHardfork::Frontier |
|
||||
EthereumHardfork::Homestead |
|
||||
EthereumHardfork::Dao |
|
||||
EthereumHardfork::Tangerine |
|
||||
EthereumHardfork::SpuriousDragon |
|
||||
EthereumHardfork::Byzantium |
|
||||
EthereumHardfork::Constantinople |
|
||||
EthereumHardfork::Petersburg |
|
||||
EthereumHardfork::Istanbul |
|
||||
EthereumHardfork::MuirGlacier |
|
||||
EthereumHardfork::Berlin |
|
||||
EthereumHardfork::London |
|
||||
EthereumHardfork::ArrowGlacier |
|
||||
EthereumHardfork::GrayGlacier |
|
||||
EthereumHardfork::Paris |
|
||||
EthereumHardfork::Shanghai => Some(1704992401),
|
||||
EthereumHardfork::Cancun => Some(1710374401),
|
||||
_ => None,
|
||||
},
|
||||
|fork| match fork {
|
||||
Self::Bedrock | Self::Regolith => Some(1686789347),
|
||||
Self::Canyon => Some(1704992401),
|
||||
Self::Ecotone => Some(1710374401),
|
||||
Self::Fjord => Some(1720627201),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
/// Optimism mainnet list of hardforks.
|
||||
pub fn op_mainnet() -> ChainHardforks {
|
||||
ChainHardforks::new(vec![
|
||||
(EthereumHardfork::Frontier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Homestead.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Tangerine.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::SpuriousDragon.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Byzantium.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Constantinople.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Petersburg.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Istanbul.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::MuirGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Berlin.boxed(), ForkCondition::Block(3950000)),
|
||||
(EthereumHardfork::London.boxed(), ForkCondition::Block(105235063)),
|
||||
(EthereumHardfork::ArrowGlacier.boxed(), ForkCondition::Block(105235063)),
|
||||
(EthereumHardfork::GrayGlacier.boxed(), ForkCondition::Block(105235063)),
|
||||
(
|
||||
EthereumHardfork::Paris.boxed(),
|
||||
ForkCondition::TTD { fork_block: Some(105235063), total_difficulty: U256::ZERO },
|
||||
),
|
||||
(Self::Bedrock.boxed(), ForkCondition::Block(105235063)),
|
||||
(Self::Regolith.boxed(), ForkCondition::Timestamp(0)),
|
||||
(EthereumHardfork::Shanghai.boxed(), ForkCondition::Timestamp(1704992401)),
|
||||
(Self::Canyon.boxed(), ForkCondition::Timestamp(1704992401)),
|
||||
(EthereumHardfork::Cancun.boxed(), ForkCondition::Timestamp(1710374401)),
|
||||
(Self::Ecotone.boxed(), ForkCondition::Timestamp(1710374401)),
|
||||
(Self::Fjord.boxed(), ForkCondition::Timestamp(1720627201)),
|
||||
])
|
||||
}
|
||||
|
||||
/// Optimism sepolia list of hardforks.
|
||||
pub fn op_sepolia() -> ChainHardforks {
|
||||
ChainHardforks::new(vec![
|
||||
(EthereumHardfork::Frontier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Homestead.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Tangerine.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::SpuriousDragon.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Byzantium.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Constantinople.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Petersburg.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Istanbul.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::MuirGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Berlin.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::London.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::ArrowGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::GrayGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(
|
||||
EthereumHardfork::Paris.boxed(),
|
||||
ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO },
|
||||
),
|
||||
(Self::Bedrock.boxed(), ForkCondition::Block(0)),
|
||||
(Self::Regolith.boxed(), ForkCondition::Timestamp(0)),
|
||||
(EthereumHardfork::Shanghai.boxed(), ForkCondition::Timestamp(1699981200)),
|
||||
(Self::Canyon.boxed(), ForkCondition::Timestamp(1699981200)),
|
||||
(EthereumHardfork::Cancun.boxed(), ForkCondition::Timestamp(1708534800)),
|
||||
(Self::Ecotone.boxed(), ForkCondition::Timestamp(1708534800)),
|
||||
(Self::Fjord.boxed(), ForkCondition::Timestamp(1716998400)),
|
||||
])
|
||||
}
|
||||
|
||||
/// Base sepolia list of hardforks.
|
||||
pub fn base_sepolia() -> ChainHardforks {
|
||||
ChainHardforks::new(vec![
|
||||
(EthereumHardfork::Frontier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Homestead.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Tangerine.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::SpuriousDragon.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Byzantium.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Constantinople.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Petersburg.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Istanbul.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::MuirGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Berlin.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::London.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::ArrowGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::GrayGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(
|
||||
EthereumHardfork::Paris.boxed(),
|
||||
ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO },
|
||||
),
|
||||
(Self::Bedrock.boxed(), ForkCondition::Block(0)),
|
||||
(Self::Regolith.boxed(), ForkCondition::Timestamp(0)),
|
||||
(EthereumHardfork::Shanghai.boxed(), ForkCondition::Timestamp(1699981200)),
|
||||
(Self::Canyon.boxed(), ForkCondition::Timestamp(1699981200)),
|
||||
(EthereumHardfork::Cancun.boxed(), ForkCondition::Timestamp(1708534800)),
|
||||
(Self::Ecotone.boxed(), ForkCondition::Timestamp(1708534800)),
|
||||
(Self::Fjord.boxed(), ForkCondition::Timestamp(1716998400)),
|
||||
])
|
||||
}
|
||||
|
||||
/// Base mainnet list of hardforks.
|
||||
pub fn base_mainnet() -> ChainHardforks {
|
||||
ChainHardforks::new(vec![
|
||||
(EthereumHardfork::Frontier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Homestead.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Tangerine.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::SpuriousDragon.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Byzantium.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Constantinople.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Petersburg.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Istanbul.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::MuirGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Berlin.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::London.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::ArrowGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::GrayGlacier.boxed(), ForkCondition::Block(0)),
|
||||
(
|
||||
EthereumHardfork::Paris.boxed(),
|
||||
ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO },
|
||||
),
|
||||
(Self::Bedrock.boxed(), ForkCondition::Block(0)),
|
||||
(Self::Regolith.boxed(), ForkCondition::Timestamp(0)),
|
||||
(EthereumHardfork::Shanghai.boxed(), ForkCondition::Timestamp(1704992401)),
|
||||
(Self::Canyon.boxed(), ForkCondition::Timestamp(1704992401)),
|
||||
(EthereumHardfork::Cancun.boxed(), ForkCondition::Timestamp(1710374401)),
|
||||
(Self::Ecotone.boxed(), ForkCondition::Timestamp(1710374401)),
|
||||
(Self::Fjord.boxed(), ForkCondition::Timestamp(1720627201)),
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
/// Match helper method since it's not possible to match on `dyn Hardfork`
|
||||
fn match_hardfork<H, HF, OHF>(fork: H, hardfork_fn: HF, optimism_hardfork_fn: OHF) -> Option<u64>
|
||||
where
|
||||
H: Hardfork,
|
||||
HF: Fn(&EthereumHardfork) -> Option<u64>,
|
||||
OHF: Fn(&OptimismHardfork) -> Option<u64>,
|
||||
{
|
||||
let fork: &dyn Any = ⋔
|
||||
if let Some(fork) = fork.downcast_ref::<EthereumHardfork>() {
|
||||
return hardfork_fn(fork)
|
||||
}
|
||||
fork.downcast_ref::<OptimismHardfork>().and_then(optimism_hardfork_fn)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_match_hardfork() {
|
||||
assert_eq!(
|
||||
OptimismHardfork::base_mainnet_activation_block(EthereumHardfork::Cancun),
|
||||
Some(11188936)
|
||||
);
|
||||
assert_eq!(
|
||||
OptimismHardfork::base_mainnet_activation_block(OptimismHardfork::Canyon),
|
||||
Some(9101527)
|
||||
);
|
||||
}
|
||||
}
|
||||
56
crates/ethereum-forks/src/hardforks/ethereum.rs
Normal file
56
crates/ethereum-forks/src/hardforks/ethereum.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use crate::{
|
||||
hardforks::{ChainHardforks, Hardforks},
|
||||
EthereumHardfork, ForkCondition,
|
||||
};
|
||||
|
||||
/// Helper methods for Ethereum forks.
|
||||
pub trait EthereumHardforks: Hardforks {
|
||||
/// Convenience method to check if [`EthereumHardfork::Shanghai`] is active at a given
|
||||
/// timestamp.
|
||||
fn is_shanghai_active_at_timestamp(&self, timestamp: u64) -> bool {
|
||||
self.is_fork_active_at_timestamp(EthereumHardfork::Shanghai, timestamp)
|
||||
}
|
||||
|
||||
/// Convenience method to check if [`EthereumHardfork::Cancun`] is active at a given timestamp.
|
||||
fn is_cancun_active_at_timestamp(&self, timestamp: u64) -> bool {
|
||||
self.is_fork_active_at_timestamp(EthereumHardfork::Cancun, timestamp)
|
||||
}
|
||||
|
||||
/// Convenience method to check if [`EthereumHardfork::Prague`] is active at a given timestamp.
|
||||
fn is_prague_active_at_timestamp(&self, timestamp: u64) -> bool {
|
||||
self.is_fork_active_at_timestamp(EthereumHardfork::Prague, timestamp)
|
||||
}
|
||||
|
||||
/// Convenience method to check if [`EthereumHardfork::Byzantium`] is active at a given block
|
||||
/// number.
|
||||
fn is_byzantium_active_at_block(&self, block_number: u64) -> bool {
|
||||
self.fork(EthereumHardfork::Byzantium).active_at_block(block_number)
|
||||
}
|
||||
|
||||
/// Convenience method to check if [`EthereumHardfork::SpuriousDragon`] is active at a given
|
||||
/// block number.
|
||||
fn is_spurious_dragon_active_at_block(&self, block_number: u64) -> bool {
|
||||
self.fork(EthereumHardfork::SpuriousDragon).active_at_block(block_number)
|
||||
}
|
||||
|
||||
/// Convenience method to check if [`EthereumHardfork::Homestead`] is active at a given block
|
||||
/// number.
|
||||
fn is_homestead_active_at_block(&self, block_number: u64) -> bool {
|
||||
self.fork(EthereumHardfork::Homestead).active_at_block(block_number)
|
||||
}
|
||||
|
||||
/// The Paris hardfork (merge) is activated via block number. If we have knowledge of the block,
|
||||
/// this function will return true if the block number is greater than or equal to the Paris
|
||||
/// (merge) block.
|
||||
fn is_paris_active_at_block(&self, block_number: u64) -> Option<bool> {
|
||||
match self.fork(EthereumHardfork::Paris) {
|
||||
ForkCondition::Block(paris_block) => Some(block_number >= paris_block),
|
||||
ForkCondition::TTD { fork_block, .. } => {
|
||||
fork_block.map(|paris_block| block_number >= paris_block)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EthereumHardforks for ChainHardforks {}
|
||||
131
crates/ethereum-forks/src/hardforks/mod.rs
Normal file
131
crates/ethereum-forks/src/hardforks/mod.rs
Normal file
@ -0,0 +1,131 @@
|
||||
/// Ethereum helper methods
|
||||
mod ethereum;
|
||||
pub use ethereum::EthereumHardforks;
|
||||
|
||||
/// Optimism helper methods
|
||||
mod optimism;
|
||||
pub use optimism::OptimismHardforks;
|
||||
|
||||
use crate::{ForkCondition, Hardfork};
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
/// Generic trait over a set of ordered hardforks
|
||||
pub trait Hardforks: Default + Clone {
|
||||
/// Retrieves [`ForkCondition`] from `fork`. If `fork` is not present, returns
|
||||
/// [`ForkCondition::Never`].
|
||||
fn fork<H: Hardfork>(&self, fork: H) -> ForkCondition;
|
||||
|
||||
/// Get an iterator of all hardforks with their respective activation conditions.
|
||||
fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, ForkCondition)>;
|
||||
|
||||
/// Convenience method to check if a fork is active at a given timestamp.
|
||||
fn is_fork_active_at_timestamp<H: Hardfork>(&self, fork: H, timestamp: u64) -> bool {
|
||||
self.fork(fork).active_at_timestamp(timestamp)
|
||||
}
|
||||
|
||||
/// Convenience method to check if a fork is active at a given block number.
|
||||
fn is_fork_active_at_block<H: Hardfork>(&self, fork: H, block_number: u64) -> bool {
|
||||
self.fork(fork).active_at_block(block_number)
|
||||
}
|
||||
}
|
||||
|
||||
/// Ordered list of a chain hardforks that implement [`Hardfork`].
|
||||
#[derive(Default, Clone, PartialEq, Eq)]
|
||||
pub struct ChainHardforks {
|
||||
forks: Vec<(Box<dyn Hardfork>, ForkCondition)>,
|
||||
map: FxHashMap<&'static str, ForkCondition>,
|
||||
}
|
||||
|
||||
impl ChainHardforks {
|
||||
/// Creates a new [`ChainHardforks`] from a list which **must be ordered** by activation.
|
||||
///
|
||||
/// Equivalent Ethereum hardforks **must be included** as well.
|
||||
pub fn new(forks: Vec<(Box<dyn Hardfork>, ForkCondition)>) -> Self {
|
||||
let map = forks.iter().map(|(fork, condition)| (fork.name(), *condition)).collect();
|
||||
|
||||
Self { forks, map }
|
||||
}
|
||||
|
||||
/// Total number of hardforks.
|
||||
pub fn len(&self) -> usize {
|
||||
self.forks.len()
|
||||
}
|
||||
|
||||
/// Checks if the fork list is empty.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.forks.is_empty()
|
||||
}
|
||||
|
||||
/// Retrieves [`ForkCondition`] from `fork`. If `fork` is not present, returns
|
||||
/// [`ForkCondition::Never`].
|
||||
pub fn fork<H: Hardfork>(&self, fork: H) -> ForkCondition {
|
||||
self.get(fork).unwrap_or(ForkCondition::Never)
|
||||
}
|
||||
|
||||
/// Retrieves [`ForkCondition`] from `fork` if it exists, otherwise `None`.
|
||||
pub fn get<H: Hardfork>(&self, fork: H) -> Option<ForkCondition> {
|
||||
self.map.get(fork.name()).copied()
|
||||
}
|
||||
|
||||
/// Get an iterator of all hardforks with their respective activation conditions.
|
||||
pub fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, ForkCondition)> {
|
||||
self.forks.iter().map(|(f, b)| (&**f, *b))
|
||||
}
|
||||
|
||||
/// Get last hardfork from the list.
|
||||
pub fn last(&self) -> Option<(Box<dyn Hardfork>, ForkCondition)> {
|
||||
self.forks.last().map(|(f, b)| (f.clone(), *b))
|
||||
}
|
||||
|
||||
/// Convenience method to check if a fork is active at a given timestamp.
|
||||
pub fn is_fork_active_at_timestamp<H: Hardfork>(&self, fork: H, timestamp: u64) -> bool {
|
||||
self.fork(fork).active_at_timestamp(timestamp)
|
||||
}
|
||||
|
||||
/// Convenience method to check if a fork is active at a given block number.
|
||||
pub fn is_fork_active_at_block<H: Hardfork>(&self, fork: H, block_number: u64) -> bool {
|
||||
self.fork(fork).active_at_block(block_number)
|
||||
}
|
||||
|
||||
/// Inserts `fork` into list, updating with a new [`ForkCondition`] if it already exists.
|
||||
pub fn insert<H: Hardfork>(&mut self, fork: H, condition: ForkCondition) {
|
||||
match self.map.entry(fork.name()) {
|
||||
std::collections::hash_map::Entry::Occupied(mut entry) => {
|
||||
*entry.get_mut() = condition;
|
||||
if let Some((_, inner)) =
|
||||
self.forks.iter_mut().find(|(inner, _)| inner.name() == fork.name())
|
||||
{
|
||||
*inner = condition;
|
||||
}
|
||||
}
|
||||
std::collections::hash_map::Entry::Vacant(entry) => {
|
||||
entry.insert(condition);
|
||||
self.forks.push((Box::new(fork), condition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes `fork` from list.
|
||||
pub fn remove<H: Hardfork>(&mut self, fork: H) {
|
||||
self.forks.retain(|(inner_fork, _)| inner_fork.name() != fork.name());
|
||||
self.map.remove(fork.name());
|
||||
}
|
||||
}
|
||||
|
||||
impl Hardforks for ChainHardforks {
|
||||
fn fork<H: Hardfork>(&self, fork: H) -> ForkCondition {
|
||||
self.fork(fork)
|
||||
}
|
||||
|
||||
fn forks_iter(&self) -> impl Iterator<Item = (&dyn Hardfork, ForkCondition)> {
|
||||
self.forks_iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl core::fmt::Debug for ChainHardforks {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
f.debug_struct("ChainHardforks")
|
||||
.field("0", &self.forks_iter().map(|(hf, cond)| (hf.name(), cond)).collect::<Vec<_>>())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
12
crates/ethereum-forks/src/hardforks/optimism.rs
Normal file
12
crates/ethereum-forks/src/hardforks/optimism.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use crate::{ChainHardforks, EthereumHardforks, OptimismHardfork};
|
||||
|
||||
/// Extends [`crate::EthereumHardforks`] with optimism helper methods.
|
||||
pub trait OptimismHardforks: EthereumHardforks {
|
||||
/// Convenience method to check if [`OptimismHardfork::Bedrock`] is active at a given block
|
||||
/// number.
|
||||
fn is_bedrock_active_at_block(&self, block_number: u64) -> bool {
|
||||
self.fork(OptimismHardfork::Bedrock).active_at_block(block_number)
|
||||
}
|
||||
}
|
||||
|
||||
impl OptimismHardforks for ChainHardforks {}
|
||||
@ -22,19 +22,18 @@ mod display;
|
||||
mod forkcondition;
|
||||
mod forkid;
|
||||
mod hardfork;
|
||||
mod hardforks;
|
||||
mod head;
|
||||
|
||||
pub use forkid::{
|
||||
EnrForkIdEntry, ForkFilter, ForkFilterKey, ForkHash, ForkId, ForkTransition, ValidationError,
|
||||
};
|
||||
pub use hardfork::Hardfork;
|
||||
pub use hardfork::{EthereumHardfork, Hardfork, OptimismHardfork, DEV_HARDFORKS};
|
||||
pub use head::Head;
|
||||
|
||||
pub use display::DisplayHardforks;
|
||||
pub use forkcondition::ForkCondition;
|
||||
|
||||
/// Chains hardforks
|
||||
pub mod chains;
|
||||
pub use hardforks::*;
|
||||
|
||||
#[cfg(any(test, feature = "arbitrary"))]
|
||||
pub use arbitrary;
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
|
||||
use reth_chainspec::{Chain, ChainSpec, Hardfork};
|
||||
use reth_chainspec::{Chain, ChainSpec, EthereumHardfork, EthereumHardforks};
|
||||
use reth_consensus::{Consensus, ConsensusError, PostExecutionInput};
|
||||
use reth_consensus_common::validation::{
|
||||
validate_4844_header_standalone, validate_against_parent_4844,
|
||||
@ -51,7 +51,7 @@ impl EthBeaconConsensus {
|
||||
) -> Result<(), ConsensusError> {
|
||||
// Determine the parent gas limit, considering elasticity multiplier on the London fork.
|
||||
let parent_gas_limit =
|
||||
if self.chain_spec.fork(Hardfork::London).transitions_at_block(header.number) {
|
||||
if self.chain_spec.fork(EthereumHardfork::London).transitions_at_block(header.number) {
|
||||
parent.gas_limit *
|
||||
self.chain_spec
|
||||
.base_fee_params_at_timestamp(header.timestamp)
|
||||
@ -153,7 +153,7 @@ impl Consensus for EthBeaconConsensus {
|
||||
) -> Result<(), ConsensusError> {
|
||||
let is_post_merge = self
|
||||
.chain_spec
|
||||
.fork(Hardfork::Paris)
|
||||
.fork(EthereumHardfork::Paris)
|
||||
.active_at_ttd(total_difficulty, header.difficulty);
|
||||
|
||||
if is_post_merge {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_consensus::ConsensusError;
|
||||
use reth_primitives::{
|
||||
gas_spent_by_transactions, BlockWithSenders, Bloom, GotExpected, Receipt, Request, B256,
|
||||
|
||||
@ -5,7 +5,7 @@ use reth_chainspec::ChainSpec;
|
||||
use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes};
|
||||
use reth_primitives::{
|
||||
constants::EIP1559_INITIAL_BASE_FEE, revm::config::revm_spec_by_timestamp_after_merge, Address,
|
||||
BlobTransactionSidecar, Hardfork, Header, SealedBlock, Withdrawals, B256, U256,
|
||||
BlobTransactionSidecar, EthereumHardfork, Header, SealedBlock, Withdrawals, B256, U256,
|
||||
};
|
||||
use reth_rpc_types::engine::{
|
||||
ExecutionPayloadEnvelopeV2, ExecutionPayloadEnvelopeV3, ExecutionPayloadEnvelopeV4,
|
||||
@ -266,7 +266,7 @@ impl PayloadBuilderAttributes for EthPayloadBuilderAttributes {
|
||||
|
||||
// If we are on the London fork boundary, we need to multiply the parent's gas limit by the
|
||||
// elasticity multiplier to get the new gas limit.
|
||||
if chain_spec.fork(Hardfork::London).transitions_at_block(parent.number + 1) {
|
||||
if chain_spec.fork(EthereumHardfork::London).transitions_at_block(parent.number + 1) {
|
||||
let elasticity_multiplier =
|
||||
chain_spec.base_fee_params_at_timestamp(self.timestamp()).elasticity_multiplier;
|
||||
|
||||
|
||||
@ -4,9 +4,7 @@ use crate::{
|
||||
dao_fork::{DAO_HARDFORK_BENEFICIARY, DAO_HARDKFORK_ACCOUNTS},
|
||||
EthEvmConfig,
|
||||
};
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::{sync::Arc, vec, vec::Vec};
|
||||
use reth_chainspec::{ChainSpec, MAINNET};
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks, MAINNET};
|
||||
use reth_ethereum_consensus::validate_block_post_execution;
|
||||
use reth_evm::{
|
||||
execute::{
|
||||
@ -17,7 +15,7 @@ use reth_evm::{
|
||||
};
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_primitives::{
|
||||
BlockNumber, BlockWithSenders, Hardfork, Header, Receipt, Request, Withdrawals, U256,
|
||||
BlockNumber, BlockWithSenders, EthereumHardfork, Header, Receipt, Request, Withdrawals, U256,
|
||||
};
|
||||
use reth_prune_types::PruneModes;
|
||||
use reth_revm::{
|
||||
@ -35,7 +33,7 @@ use revm_primitives::{
|
||||
};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::{fmt::Display, sync::Arc};
|
||||
use std::{fmt::Display, sync::Arc, vec, vec::Vec};
|
||||
/// Provides executors to execute regular ethereum blocks
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct EthExecutorProvider<EvmConfig = EthEvmConfig> {
|
||||
@ -342,7 +340,7 @@ where
|
||||
);
|
||||
|
||||
// Irregular state change at Ethereum DAO hardfork
|
||||
if self.chain_spec().fork(Hardfork::Dao).transitions_at_block(block.number) {
|
||||
if self.chain_spec().fork(EthereumHardfork::Dao).transitions_at_block(block.number) {
|
||||
// drain balances from hardcoded addresses.
|
||||
let drained_balance: u128 = self
|
||||
.state
|
||||
@ -539,7 +537,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Cancun, ForkCondition::Timestamp(1))
|
||||
.with_fork(EthereumHardfork::Cancun, ForkCondition::Timestamp(1))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -636,7 +634,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Cancun, ForkCondition::Timestamp(1))
|
||||
.with_fork(EthereumHardfork::Cancun, ForkCondition::Timestamp(1))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -679,7 +677,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Cancun, ForkCondition::Timestamp(1))
|
||||
.with_fork(EthereumHardfork::Cancun, ForkCondition::Timestamp(1))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -732,7 +730,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Cancun, ForkCondition::Timestamp(0))
|
||||
.with_fork(EthereumHardfork::Cancun, ForkCondition::Timestamp(0))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -819,7 +817,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Cancun, ForkCondition::Timestamp(1))
|
||||
.with_fork(EthereumHardfork::Cancun, ForkCondition::Timestamp(1))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -889,7 +887,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Prague, ForkCondition::Never)
|
||||
.with_fork(EthereumHardfork::Prague, ForkCondition::Never)
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -942,7 +940,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Prague, ForkCondition::Timestamp(0))
|
||||
.with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(0))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -994,7 +992,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Prague, ForkCondition::Timestamp(1))
|
||||
.with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(1))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -1057,7 +1055,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Prague, ForkCondition::Timestamp(1))
|
||||
.with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(1))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -1116,7 +1114,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Prague, ForkCondition::Timestamp(0))
|
||||
.with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(0))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -1253,7 +1251,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Prague, ForkCondition::Timestamp(0))
|
||||
.with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(0))
|
||||
.build(),
|
||||
);
|
||||
|
||||
@ -1334,7 +1332,7 @@ mod tests {
|
||||
let chain_spec = Arc::new(
|
||||
ChainSpecBuilder::from(&*MAINNET)
|
||||
.shanghai_activated()
|
||||
.with_fork(Hardfork::Prague, ForkCondition::Timestamp(0))
|
||||
.with_fork(EthereumHardfork::Prague, ForkCondition::Timestamp(0))
|
||||
.build(),
|
||||
);
|
||||
|
||||
|
||||
@ -28,7 +28,8 @@ use reth_primitives::{
|
||||
eip4844::calculate_excess_blob_gas,
|
||||
proofs::{self, calculate_requests_root},
|
||||
revm::env::tx_env_with_recovered,
|
||||
Block, Header, IntoRecoveredTransaction, Receipt, EMPTY_OMMER_ROOT_HASH, U256,
|
||||
Block, EthereumHardforks, Header, IntoRecoveredTransaction, Receipt, EMPTY_OMMER_ROOT_HASH,
|
||||
U256,
|
||||
};
|
||||
use reth_provider::StateProviderFactory;
|
||||
use reth_revm::{database::StateProviderDatabase, state_change::apply_blockhashes_update};
|
||||
|
||||
@ -58,7 +58,7 @@ mod tests {
|
||||
use super::*;
|
||||
use alloy_rlp::Encodable;
|
||||
use discv5::enr::{CombinedKey, EnrKey};
|
||||
use reth_chainspec::{Hardfork, MAINNET};
|
||||
use reth_chainspec::{EthereumHardfork, MAINNET};
|
||||
use reth_network_peers::NodeRecord;
|
||||
|
||||
#[test]
|
||||
@ -84,7 +84,7 @@ mod tests {
|
||||
let key = CombinedKey::generate_secp256k1();
|
||||
|
||||
let mut buf = Vec::new();
|
||||
let fork_id = MAINNET.hardfork_fork_id(Hardfork::Frontier);
|
||||
let fork_id = MAINNET.hardfork_fork_id(EthereumHardfork::Frontier);
|
||||
fork_id.unwrap().encode(&mut buf);
|
||||
|
||||
let enr = Enr::builder()
|
||||
|
||||
@ -415,7 +415,7 @@ mod tests {
|
||||
use alloy_rlp::{Decodable, Encodable};
|
||||
use enr::EnrKey;
|
||||
use reth_chainspec::MAINNET;
|
||||
use reth_ethereum_forks::{ForkHash, Hardfork};
|
||||
use reth_ethereum_forks::{EthereumHardfork, ForkHash};
|
||||
use secp256k1::rand::thread_rng;
|
||||
use std::{future::poll_fn, net::Ipv4Addr};
|
||||
|
||||
@ -513,7 +513,7 @@ mod tests {
|
||||
resolver.insert(link.domain.clone(), root.to_string());
|
||||
|
||||
let mut builder = Enr::builder();
|
||||
let fork_id = MAINNET.hardfork_fork_id(Hardfork::Frontier).unwrap();
|
||||
let fork_id = MAINNET.hardfork_fork_id(EthereumHardfork::Frontier).unwrap();
|
||||
builder
|
||||
.ip4(Ipv4Addr::LOCALHOST)
|
||||
.udp4(30303)
|
||||
|
||||
@ -3,7 +3,7 @@ use alloy_genesis::Genesis;
|
||||
use alloy_rlp::{RlpDecodable, RlpEncodable};
|
||||
use reth_chainspec::{Chain, ChainSpec, NamedChain, MAINNET};
|
||||
use reth_codecs_derive::derive_arbitrary;
|
||||
use reth_primitives::{hex, ForkId, Hardfork, Head, B256, U256};
|
||||
use reth_primitives::{hex, EthereumHardfork, ForkId, Head, B256, U256};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{Debug, Display};
|
||||
@ -142,7 +142,7 @@ impl Default for Status {
|
||||
blockhash: mainnet_genesis,
|
||||
genesis: mainnet_genesis,
|
||||
forkid: MAINNET
|
||||
.hardfork_fork_id(Hardfork::Frontier)
|
||||
.hardfork_fork_id(EthereumHardfork::Frontier)
|
||||
.expect("The Frontier hardfork should always exist"),
|
||||
}
|
||||
}
|
||||
@ -152,7 +152,7 @@ impl Default for Status {
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use reth_chainspec::{Chain, Hardfork, MAINNET};
|
||||
/// use reth_chainspec::{Chain, EthereumHardfork, MAINNET};
|
||||
/// use reth_eth_wire_types::{EthVersion, Status};
|
||||
/// use reth_primitives::{B256, MAINNET_GENESIS_HASH, U256};
|
||||
///
|
||||
@ -163,7 +163,7 @@ impl Default for Status {
|
||||
/// .total_difficulty(U256::from(100))
|
||||
/// .blockhash(B256::from(MAINNET_GENESIS_HASH))
|
||||
/// .genesis(B256::from(MAINNET_GENESIS_HASH))
|
||||
/// .forkid(MAINNET.hardfork_fork_id(Hardfork::Paris).unwrap())
|
||||
/// .forkid(MAINNET.hardfork_fork_id(EthereumHardfork::Paris).unwrap())
|
||||
/// .build();
|
||||
///
|
||||
/// assert_eq!(
|
||||
@ -174,7 +174,7 @@ impl Default for Status {
|
||||
/// total_difficulty: U256::from(100),
|
||||
/// blockhash: B256::from(MAINNET_GENESIS_HASH),
|
||||
/// genesis: B256::from(MAINNET_GENESIS_HASH),
|
||||
/// forkid: MAINNET.hardfork_fork_id(Hardfork::Paris).unwrap(),
|
||||
/// forkid: MAINNET.hardfork_fork_id(EthereumHardfork::Paris).unwrap(),
|
||||
/// }
|
||||
/// );
|
||||
/// ```
|
||||
@ -233,7 +233,7 @@ mod tests {
|
||||
use alloy_rlp::{Decodable, Encodable};
|
||||
use rand::Rng;
|
||||
use reth_chainspec::{Chain, ChainSpec, ForkCondition, NamedChain};
|
||||
use reth_primitives::{hex, ForkHash, ForkId, Hardfork, Head, B256, U256};
|
||||
use reth_primitives::{hex, EthereumHardfork, ForkHash, ForkId, Head, B256, U256};
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
@ -368,12 +368,12 @@ mod tests {
|
||||
|
||||
// add a few hardforks
|
||||
let hardforks = vec![
|
||||
(Hardfork::Tangerine, ForkCondition::Block(1)),
|
||||
(Hardfork::SpuriousDragon, ForkCondition::Block(2)),
|
||||
(Hardfork::Byzantium, ForkCondition::Block(3)),
|
||||
(Hardfork::MuirGlacier, ForkCondition::Block(5)),
|
||||
(Hardfork::London, ForkCondition::Block(8)),
|
||||
(Hardfork::Shanghai, ForkCondition::Timestamp(13)),
|
||||
(EthereumHardfork::Tangerine, ForkCondition::Block(1)),
|
||||
(EthereumHardfork::SpuriousDragon, ForkCondition::Block(2)),
|
||||
(EthereumHardfork::Byzantium, ForkCondition::Block(3)),
|
||||
(EthereumHardfork::MuirGlacier, ForkCondition::Block(5)),
|
||||
(EthereumHardfork::London, ForkCondition::Block(8)),
|
||||
(EthereumHardfork::Shanghai, ForkCondition::Timestamp(13)),
|
||||
];
|
||||
|
||||
let mut chainspec = ChainSpec::builder().genesis(genesis).chain(Chain::from_id(1337));
|
||||
|
||||
@ -563,7 +563,6 @@ mod tests {
|
||||
use reth_dns_discovery::tree::LinkEntry;
|
||||
use reth_primitives::ForkHash;
|
||||
use reth_provider::test_utils::NoopProvider;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
fn builder() -> NetworkConfigBuilder {
|
||||
let secret_key = SecretKey::new(&mut thread_rng());
|
||||
@ -587,7 +586,7 @@ mod tests {
|
||||
let mut chain_spec = Arc::clone(&MAINNET);
|
||||
|
||||
// remove any `next` fields we would have by removing all hardforks
|
||||
Arc::make_mut(&mut chain_spec).hardforks = BTreeMap::new();
|
||||
Arc::make_mut(&mut chain_spec).hardforks = Default::default();
|
||||
|
||||
// check that the forkid is initialized with the genesis and no other forks
|
||||
let genesis_fork_hash = ForkHash::from(chain_spec.genesis_hash());
|
||||
|
||||
@ -768,7 +768,7 @@ mod tests {
|
||||
};
|
||||
use reth_network_peers::pk2id;
|
||||
use reth_network_types::session::config::PROTOCOL_BREACH_REQUEST_TIMEOUT;
|
||||
use reth_primitives::{ForkFilter, Hardfork};
|
||||
use reth_primitives::{EthereumHardfork, ForkFilter};
|
||||
use secp256k1::{SecretKey, SECP256K1};
|
||||
use tokio::{
|
||||
net::{TcpListener, TcpStream},
|
||||
@ -918,7 +918,7 @@ mod tests {
|
||||
local_peer_id,
|
||||
status: StatusBuilder::default().build(),
|
||||
fork_filter: MAINNET
|
||||
.hardfork_fork_filter(Hardfork::Frontier)
|
||||
.hardfork_fork_filter(EthereumHardfork::Frontier)
|
||||
.expect("The Frontier fork filter should exist on mainnet"),
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
// The `optimism` feature must be enabled to use this crate.
|
||||
#![cfg(feature = "optimism")]
|
||||
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks, OptimismHardforks};
|
||||
use reth_consensus::{Consensus, ConsensusError, PostExecutionInput};
|
||||
use reth_consensus_common::validation::{
|
||||
validate_against_parent_4844, validate_against_parent_eip1559_base_fee,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_consensus::ConsensusError;
|
||||
use reth_primitives::{
|
||||
gas_spent_by_transactions, proofs::calculate_receipt_root_optimism, BlockWithSenders, Bloom,
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! Optimism block executor.
|
||||
|
||||
use crate::{l1::ensure_create2_deployer, OptimismBlockExecutionError, OptimismEvmConfig};
|
||||
use reth_chainspec::{ChainSpec, Hardfork};
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks, OptimismHardfork};
|
||||
use reth_evm::{
|
||||
execute::{
|
||||
BatchExecutor, BlockExecutionError, BlockExecutionInput, BlockExecutionOutput,
|
||||
@ -133,7 +133,7 @@ where
|
||||
|
||||
// execute transactions
|
||||
let is_regolith =
|
||||
self.chain_spec.fork(Hardfork::Regolith).active_at_timestamp(block.timestamp);
|
||||
self.chain_spec.fork(OptimismHardfork::Regolith).active_at_timestamp(block.timestamp);
|
||||
|
||||
// Ensure that the create2deployer is force-deployed at the canyon transition. Optimism
|
||||
// blocks will always have at least a single transaction in them (the L1 info transaction),
|
||||
@ -220,7 +220,7 @@ where
|
||||
// this is only set for post-Canyon deposit transactions.
|
||||
deposit_receipt_version: (transaction.is_deposit() &&
|
||||
self.chain_spec
|
||||
.is_fork_active_at_timestamp(Hardfork::Canyon, block.timestamp))
|
||||
.is_fork_active_at_timestamp(OptimismHardfork::Canyon, block.timestamp))
|
||||
.then_some(1),
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! Optimism-specific implementation and utilities for the executor
|
||||
|
||||
use crate::OptimismBlockExecutionError;
|
||||
use reth_chainspec::{ChainSpec, Hardfork};
|
||||
use reth_chainspec::{ChainSpec, OptimismHardfork};
|
||||
use reth_execution_errors::BlockExecutionError;
|
||||
use reth_primitives::{address, b256, hex, Address, Block, Bytes, B256, U256};
|
||||
use revm::{
|
||||
@ -191,13 +191,14 @@ impl RethL1BlockInfo for L1BlockInfo {
|
||||
return Ok(U256::ZERO)
|
||||
}
|
||||
|
||||
let spec_id = if chain_spec.is_fork_active_at_timestamp(Hardfork::Fjord, timestamp) {
|
||||
let spec_id = if chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Fjord, timestamp)
|
||||
{
|
||||
SpecId::FJORD
|
||||
} else if chain_spec.is_fork_active_at_timestamp(Hardfork::Ecotone, timestamp) {
|
||||
} else if chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Ecotone, timestamp) {
|
||||
SpecId::ECOTONE
|
||||
} else if chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, timestamp) {
|
||||
} else if chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Regolith, timestamp) {
|
||||
SpecId::REGOLITH
|
||||
} else if chain_spec.is_fork_active_at_timestamp(Hardfork::Bedrock, timestamp) {
|
||||
} else if chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Bedrock, timestamp) {
|
||||
SpecId::BEDROCK
|
||||
} else {
|
||||
return Err(OptimismBlockExecutionError::L1BlockInfoError {
|
||||
@ -214,11 +215,12 @@ impl RethL1BlockInfo for L1BlockInfo {
|
||||
timestamp: u64,
|
||||
input: &[u8],
|
||||
) -> Result<U256, BlockExecutionError> {
|
||||
let spec_id = if chain_spec.is_fork_active_at_timestamp(Hardfork::Fjord, timestamp) {
|
||||
let spec_id = if chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Fjord, timestamp)
|
||||
{
|
||||
SpecId::FJORD
|
||||
} else if chain_spec.is_fork_active_at_timestamp(Hardfork::Regolith, timestamp) {
|
||||
} else if chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Regolith, timestamp) {
|
||||
SpecId::REGOLITH
|
||||
} else if chain_spec.is_fork_active_at_timestamp(Hardfork::Bedrock, timestamp) {
|
||||
} else if chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Bedrock, timestamp) {
|
||||
SpecId::BEDROCK
|
||||
} else {
|
||||
return Err(OptimismBlockExecutionError::L1BlockInfoError {
|
||||
@ -245,8 +247,9 @@ where
|
||||
// previous block timestamp (heuristically, block time is not perfectly constant at 2s), and the
|
||||
// chain is an optimism chain, then we need to force-deploy the create2 deployer contract.
|
||||
if chain_spec.is_optimism() &&
|
||||
chain_spec.is_fork_active_at_timestamp(Hardfork::Canyon, timestamp) &&
|
||||
!chain_spec.is_fork_active_at_timestamp(Hardfork::Canyon, timestamp.saturating_sub(2))
|
||||
chain_spec.is_fork_active_at_timestamp(OptimismHardfork::Canyon, timestamp) &&
|
||||
!chain_spec
|
||||
.is_fork_active_at_timestamp(OptimismHardfork::Canyon, timestamp.saturating_sub(2))
|
||||
{
|
||||
trace!(target: "evm", "Forcing create2 deployer contract deployment on Canyon transition");
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use reth_chainspec::{ChainSpec, Hardfork};
|
||||
use reth_chainspec::{ChainSpec, OptimismHardfork};
|
||||
use reth_node_api::{
|
||||
payload::{
|
||||
validate_parent_beacon_block_root_presence, EngineApiMessageVersion,
|
||||
@ -69,7 +69,7 @@ pub fn validate_withdrawals_presence(
|
||||
timestamp: u64,
|
||||
has_withdrawals: bool,
|
||||
) -> Result<(), EngineObjectValidationError> {
|
||||
let is_shanghai = chain_spec.fork(Hardfork::Canyon).active_at_timestamp(timestamp);
|
||||
let is_shanghai = chain_spec.fork(OptimismHardfork::Canyon).active_at_timestamp(timestamp);
|
||||
|
||||
match version {
|
||||
EngineApiMessageVersion::V1 => {
|
||||
|
||||
@ -5,7 +5,7 @@ use crate::{
|
||||
payload::{OptimismBuiltPayload, OptimismPayloadBuilderAttributes},
|
||||
};
|
||||
use reth_basic_payload_builder::*;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks, OptimismHardfork};
|
||||
use reth_evm::ConfigureEvm;
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_payload_builder::error::PayloadBuilderError;
|
||||
@ -14,8 +14,7 @@ use reth_primitives::{
|
||||
eip4844::calculate_excess_blob_gas,
|
||||
proofs,
|
||||
revm::env::tx_env_with_recovered,
|
||||
Block, Hardfork, Header, IntoRecoveredTransaction, Receipt, TxType, EMPTY_OMMER_ROOT_HASH,
|
||||
U256,
|
||||
Block, Header, IntoRecoveredTransaction, Receipt, TxType, EMPTY_OMMER_ROOT_HASH, U256,
|
||||
};
|
||||
use reth_provider::StateProviderFactory;
|
||||
use reth_revm::database::StateProviderDatabase;
|
||||
@ -281,8 +280,10 @@ where
|
||||
|
||||
let block_number = initialized_block_env.number.to::<u64>();
|
||||
|
||||
let is_regolith = chain_spec
|
||||
.is_fork_active_at_timestamp(Hardfork::Regolith, attributes.payload_attributes.timestamp);
|
||||
let is_regolith = chain_spec.is_fork_active_at_timestamp(
|
||||
OptimismHardfork::Regolith,
|
||||
attributes.payload_attributes.timestamp,
|
||||
);
|
||||
|
||||
// apply eip-4788 pre block contract call
|
||||
pre_block_beacon_root_contract_call(
|
||||
@ -393,7 +394,7 @@ where
|
||||
// ensures this is only set for post-Canyon deposit transactions.
|
||||
deposit_receipt_version: chain_spec
|
||||
.is_fork_active_at_timestamp(
|
||||
Hardfork::Canyon,
|
||||
OptimismHardfork::Canyon,
|
||||
attributes.payload_attributes.timestamp,
|
||||
)
|
||||
.then_some(1),
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
//! Optimism builder support
|
||||
|
||||
use alloy_rlp::Encodable;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_payload_builder::EthPayloadBuilderAttributes;
|
||||
use reth_payload_primitives::{BuiltPayload, PayloadBuilderAttributes};
|
||||
use reth_primitives::{
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
use crate::metrics::PayloadBuilderMetrics;
|
||||
use futures_core::ready;
|
||||
use futures_util::FutureExt;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_payload_builder::{
|
||||
database::CachedReads, error::PayloadBuilderError, KeepPayloadJobAlive, PayloadId, PayloadJob,
|
||||
PayloadJobGenerator,
|
||||
|
||||
@ -20,8 +20,7 @@ pub use traits::{BuiltPayload, PayloadAttributes, PayloadBuilderAttributes};
|
||||
mod payload;
|
||||
pub use payload::PayloadOrAttributes;
|
||||
|
||||
use reth_chainspec::ChainSpec;
|
||||
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
/// The types that are used by the engine API.
|
||||
pub trait PayloadTypes: Send + Sync + Unpin + core::fmt::Debug + Clone {
|
||||
/// The built payload type.
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
#![cfg_attr(not(test), warn(unused_crate_dependencies))]
|
||||
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
|
||||
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_primitives::SealedBlock;
|
||||
use reth_rpc_types::{engine::MaybeCancunPayloadFields, ExecutionPayload, PayloadError};
|
||||
use reth_rpc_types_compat::engine::payload::try_into_block;
|
||||
|
||||
@ -4,9 +4,8 @@ use crate::{
|
||||
constants::EMPTY_OMMER_ROOT_HASH, keccak256, Header, Receipt, ReceiptWithBloom,
|
||||
ReceiptWithBloomRef, Request, TransactionSigned, Withdrawal, B256,
|
||||
};
|
||||
use reth_trie_common::root::{ordered_trie_root, ordered_trie_root_with_encoder};
|
||||
|
||||
use alloy_eips::eip7685::Encodable7685;
|
||||
use reth_trie_common::root::{ordered_trie_root, ordered_trie_root_with_encoder};
|
||||
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
@ -50,8 +49,9 @@ pub fn calculate_receipt_root_optimism(
|
||||
// encoding. In the Regolith Hardfork, we must strip the deposit nonce from the
|
||||
// receipts before calculating the receipt root. This was corrected in the Canyon
|
||||
// hardfork.
|
||||
if chain_spec.is_fork_active_at_timestamp(reth_chainspec::Hardfork::Regolith, timestamp) &&
|
||||
!chain_spec.is_fork_active_at_timestamp(reth_chainspec::Hardfork::Canyon, timestamp)
|
||||
if chain_spec.is_fork_active_at_timestamp(reth_chainspec::OptimismHardfork::Regolith, timestamp) &&
|
||||
!chain_spec
|
||||
.is_fork_active_at_timestamp(reth_chainspec::OptimismHardfork::Canyon, timestamp)
|
||||
{
|
||||
let receipts = receipts
|
||||
.iter()
|
||||
@ -98,8 +98,9 @@ pub fn calculate_receipt_root_no_memo_optimism(
|
||||
// encoding. In the Regolith Hardfork, we must strip the deposit nonce from the
|
||||
// receipts before calculating the receipt root. This was corrected in the Canyon
|
||||
// hardfork.
|
||||
if chain_spec.is_fork_active_at_timestamp(reth_chainspec::Hardfork::Regolith, timestamp) &&
|
||||
!chain_spec.is_fork_active_at_timestamp(reth_chainspec::Hardfork::Canyon, timestamp)
|
||||
if chain_spec.is_fork_active_at_timestamp(reth_chainspec::OptimismHardfork::Regolith, timestamp) &&
|
||||
!chain_spec
|
||||
.is_fork_active_at_timestamp(reth_chainspec::OptimismHardfork::Canyon, timestamp)
|
||||
{
|
||||
let receipts = receipts
|
||||
.iter()
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_ethereum_forks::{Hardfork, Head};
|
||||
#[cfg(feature = "optimism")]
|
||||
use reth_chainspec::OptimismHardfork;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_ethereum_forks::{EthereumHardfork, Head};
|
||||
|
||||
/// Returns the spec id at the given timestamp.
|
||||
///
|
||||
@ -11,13 +13,13 @@ pub fn revm_spec_by_timestamp_after_merge(
|
||||
) -> revm_primitives::SpecId {
|
||||
#[cfg(feature = "optimism")]
|
||||
if chain_spec.is_optimism() {
|
||||
return if chain_spec.fork(Hardfork::Fjord).active_at_timestamp(timestamp) {
|
||||
return if chain_spec.fork(OptimismHardfork::Fjord).active_at_timestamp(timestamp) {
|
||||
revm_primitives::FJORD
|
||||
} else if chain_spec.fork(Hardfork::Ecotone).active_at_timestamp(timestamp) {
|
||||
} else if chain_spec.fork(OptimismHardfork::Ecotone).active_at_timestamp(timestamp) {
|
||||
revm_primitives::ECOTONE
|
||||
} else if chain_spec.fork(Hardfork::Canyon).active_at_timestamp(timestamp) {
|
||||
} else if chain_spec.fork(OptimismHardfork::Canyon).active_at_timestamp(timestamp) {
|
||||
revm_primitives::CANYON
|
||||
} else if chain_spec.fork(Hardfork::Regolith).active_at_timestamp(timestamp) {
|
||||
} else if chain_spec.fork(OptimismHardfork::Regolith).active_at_timestamp(timestamp) {
|
||||
revm_primitives::REGOLITH
|
||||
} else {
|
||||
revm_primitives::BEDROCK
|
||||
@ -39,44 +41,44 @@ pub fn revm_spec_by_timestamp_after_merge(
|
||||
pub fn revm_spec(chain_spec: &ChainSpec, block: Head) -> revm_primitives::SpecId {
|
||||
#[cfg(feature = "optimism")]
|
||||
if chain_spec.is_optimism() {
|
||||
if chain_spec.fork(Hardfork::Fjord).active_at_head(&block) {
|
||||
if chain_spec.fork(OptimismHardfork::Fjord).active_at_head(&block) {
|
||||
return revm_primitives::FJORD
|
||||
} else if chain_spec.fork(Hardfork::Ecotone).active_at_head(&block) {
|
||||
} else if chain_spec.fork(OptimismHardfork::Ecotone).active_at_head(&block) {
|
||||
return revm_primitives::ECOTONE
|
||||
} else if chain_spec.fork(Hardfork::Canyon).active_at_head(&block) {
|
||||
} else if chain_spec.fork(OptimismHardfork::Canyon).active_at_head(&block) {
|
||||
return revm_primitives::CANYON
|
||||
} else if chain_spec.fork(Hardfork::Regolith).active_at_head(&block) {
|
||||
} else if chain_spec.fork(OptimismHardfork::Regolith).active_at_head(&block) {
|
||||
return revm_primitives::REGOLITH
|
||||
} else if chain_spec.fork(Hardfork::Bedrock).active_at_head(&block) {
|
||||
} else if chain_spec.fork(OptimismHardfork::Bedrock).active_at_head(&block) {
|
||||
return revm_primitives::BEDROCK
|
||||
}
|
||||
}
|
||||
|
||||
if chain_spec.fork(Hardfork::Prague).active_at_head(&block) {
|
||||
if chain_spec.fork(EthereumHardfork::Prague).active_at_head(&block) {
|
||||
revm_primitives::PRAGUE
|
||||
} else if chain_spec.fork(Hardfork::Cancun).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Cancun).active_at_head(&block) {
|
||||
revm_primitives::CANCUN
|
||||
} else if chain_spec.fork(Hardfork::Shanghai).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Shanghai).active_at_head(&block) {
|
||||
revm_primitives::SHANGHAI
|
||||
} else if chain_spec.fork(Hardfork::Paris).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Paris).active_at_head(&block) {
|
||||
revm_primitives::MERGE
|
||||
} else if chain_spec.fork(Hardfork::London).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::London).active_at_head(&block) {
|
||||
revm_primitives::LONDON
|
||||
} else if chain_spec.fork(Hardfork::Berlin).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Berlin).active_at_head(&block) {
|
||||
revm_primitives::BERLIN
|
||||
} else if chain_spec.fork(Hardfork::Istanbul).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Istanbul).active_at_head(&block) {
|
||||
revm_primitives::ISTANBUL
|
||||
} else if chain_spec.fork(Hardfork::Petersburg).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Petersburg).active_at_head(&block) {
|
||||
revm_primitives::PETERSBURG
|
||||
} else if chain_spec.fork(Hardfork::Byzantium).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Byzantium).active_at_head(&block) {
|
||||
revm_primitives::BYZANTIUM
|
||||
} else if chain_spec.fork(Hardfork::SpuriousDragon).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::SpuriousDragon).active_at_head(&block) {
|
||||
revm_primitives::SPURIOUS_DRAGON
|
||||
} else if chain_spec.fork(Hardfork::Tangerine).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Tangerine).active_at_head(&block) {
|
||||
revm_primitives::TANGERINE
|
||||
} else if chain_spec.fork(Hardfork::Homestead).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Homestead).active_at_head(&block) {
|
||||
revm_primitives::HOMESTEAD
|
||||
} else if chain_spec.fork(Hardfork::Frontier).active_at_head(&block) {
|
||||
} else if chain_spec.fork(EthereumHardfork::Frontier).active_at_head(&block) {
|
||||
revm_primitives::FRONTIER
|
||||
} else {
|
||||
panic!(
|
||||
|
||||
@ -3,7 +3,7 @@ use alloy_eips::{
|
||||
eip7002::WithdrawalRequest,
|
||||
};
|
||||
use alloy_rlp::Buf;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_consensus_common::calc;
|
||||
use reth_execution_errors::{BlockExecutionError, BlockValidationError};
|
||||
use reth_primitives::{
|
||||
|
||||
@ -10,7 +10,7 @@ use reth_payload_primitives::{
|
||||
validate_payload_timestamp, EngineApiMessageVersion, PayloadAttributes,
|
||||
PayloadBuilderAttributes, PayloadOrAttributes,
|
||||
};
|
||||
use reth_primitives::{BlockHash, BlockHashOrNumber, BlockNumber, Hardfork, B256, U64};
|
||||
use reth_primitives::{BlockHash, BlockHashOrNumber, BlockNumber, EthereumHardfork, B256, U64};
|
||||
use reth_rpc_api::EngineApiServer;
|
||||
use reth_rpc_types::engine::{
|
||||
CancunPayloadFields, ClientVersionV1, ExecutionPayload, ExecutionPayloadBodiesV1,
|
||||
@ -457,7 +457,7 @@ where
|
||||
let merge_terminal_td = self
|
||||
.inner
|
||||
.chain_spec
|
||||
.fork(Hardfork::Paris)
|
||||
.fork(EthereumHardfork::Paris)
|
||||
.ttd()
|
||||
.expect("the engine API should not be running for chains w/o paris");
|
||||
|
||||
@ -1036,7 +1036,11 @@ mod tests {
|
||||
let (handle, api) = setup_engine_api();
|
||||
|
||||
let transition_config = TransitionConfiguration {
|
||||
terminal_total_difficulty: handle.chain_spec.fork(Hardfork::Paris).ttd().unwrap() +
|
||||
terminal_total_difficulty: handle
|
||||
.chain_spec
|
||||
.fork(EthereumHardfork::Paris)
|
||||
.ttd()
|
||||
.unwrap() +
|
||||
U256::from(1),
|
||||
..Default::default()
|
||||
};
|
||||
@ -1046,7 +1050,7 @@ mod tests {
|
||||
assert_matches!(
|
||||
res,
|
||||
Err(EngineApiError::TerminalTD { execution, consensus })
|
||||
if execution == handle.chain_spec.fork(Hardfork::Paris).ttd().unwrap() && consensus == U256::from(transition_config.terminal_total_difficulty)
|
||||
if execution == handle.chain_spec.fork(EthereumHardfork::Paris).ttd().unwrap() && consensus == U256::from(transition_config.terminal_total_difficulty)
|
||||
);
|
||||
}
|
||||
|
||||
@ -1063,7 +1067,11 @@ mod tests {
|
||||
random_block(&mut rng, terminal_block_number, None, None, None);
|
||||
|
||||
let transition_config = TransitionConfiguration {
|
||||
terminal_total_difficulty: handle.chain_spec.fork(Hardfork::Paris).ttd().unwrap(),
|
||||
terminal_total_difficulty: handle
|
||||
.chain_spec
|
||||
.fork(EthereumHardfork::Paris)
|
||||
.ttd()
|
||||
.unwrap(),
|
||||
terminal_block_hash: consensus_terminal_block.hash(),
|
||||
terminal_block_number: U64::from(terminal_block_number),
|
||||
};
|
||||
@ -1101,7 +1109,11 @@ mod tests {
|
||||
random_block(&mut generators::rng(), terminal_block_number, None, None, None);
|
||||
|
||||
let transition_config = TransitionConfiguration {
|
||||
terminal_total_difficulty: handle.chain_spec.fork(Hardfork::Paris).ttd().unwrap(),
|
||||
terminal_total_difficulty: handle
|
||||
.chain_spec
|
||||
.fork(EthereumHardfork::Paris)
|
||||
.ttd()
|
||||
.unwrap(),
|
||||
terminal_block_hash: terminal_block.hash(),
|
||||
terminal_block_number: U64::from(terminal_block_number),
|
||||
};
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use futures::Future;
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_evm::ConfigureEvm;
|
||||
use reth_execution_types::ExecutionOutcome;
|
||||
use reth_primitives::{
|
||||
|
||||
@ -3,6 +3,7 @@ use std::sync::Arc;
|
||||
use alloy_rlp::{Decodable, Encodable};
|
||||
use async_trait::async_trait;
|
||||
use jsonrpsee::core::RpcResult;
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_primitives::{
|
||||
revm::env::tx_env_with_recovered, Address, Block, BlockId, BlockNumberOrTag, Bytes,
|
||||
TransactionSignedEcRecovered, Withdrawals, B256, U256,
|
||||
|
||||
@ -2,6 +2,7 @@ use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use jsonrpsee::core::RpcResult as Result;
|
||||
use reth_chainspec::EthereumHardforks;
|
||||
use reth_consensus_common::calc::{
|
||||
base_block_reward, base_block_reward_pre_merge, block_reward, ommer_reward,
|
||||
};
|
||||
|
||||
@ -620,7 +620,7 @@ mod tests {
|
||||
]),
|
||||
..Default::default()
|
||||
},
|
||||
hardforks: BTreeMap::default(),
|
||||
hardforks: Default::default(),
|
||||
genesis_hash: None,
|
||||
paris_block_and_final_difficulty: None,
|
||||
deposit_contract: None,
|
||||
|
||||
@ -14,7 +14,7 @@ use crate::{
|
||||
WithdrawalsProvider,
|
||||
};
|
||||
use itertools::{izip, Itertools};
|
||||
use reth_chainspec::{ChainInfo, ChainSpec};
|
||||
use reth_chainspec::{ChainInfo, ChainSpec, EthereumHardforks};
|
||||
use reth_db::{tables, BlockNumberList};
|
||||
use reth_db_api::{
|
||||
common::KeyValue,
|
||||
|
||||
@ -9,7 +9,7 @@ use crate::{
|
||||
EthBlobTransactionSidecar, EthPoolTransaction, LocalTransactionConfig, PoolTransaction,
|
||||
TransactionValidationOutcome, TransactionValidationTaskExecutor, TransactionValidator,
|
||||
};
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_chainspec::{ChainSpec, EthereumHardforks};
|
||||
use reth_primitives::{
|
||||
constants::{eip4844::MAX_BLOBS_PER_BLOCK, ETHEREUM_BLOCK_GAS_LIMIT},
|
||||
Address, GotExpected, InvalidTransactionError, SealedBlock, TxKind, EIP1559_TX_TYPE_ID,
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
use reth_chainspec::{net::NodeRecord, BaseFeeParams, Chain, ChainSpec, ForkCondition, Hardfork};
|
||||
use reth_chainspec::{
|
||||
net::NodeRecord, BaseFeeParams, Chain, ChainHardforks, ChainSpec, EthereumHardfork,
|
||||
ForkCondition,
|
||||
};
|
||||
use reth_primitives::{b256, B256};
|
||||
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub const SHANGHAI_TIME: u64 = 1705996800;
|
||||
|
||||
@ -13,7 +16,10 @@ pub(crate) fn bsc_chain_spec() -> Arc<ChainSpec> {
|
||||
genesis: serde_json::from_str(include_str!("./genesis.json")).expect("deserialize genesis"),
|
||||
genesis_hash: Some(GENESIS),
|
||||
paris_block_and_final_difficulty: None,
|
||||
hardforks: BTreeMap::from([(Hardfork::Shanghai, ForkCondition::Timestamp(SHANGHAI_TIME))]),
|
||||
hardforks: ChainHardforks::new(vec![(
|
||||
EthereumHardfork::Shanghai.boxed(),
|
||||
ForkCondition::Timestamp(SHANGHAI_TIME),
|
||||
)]),
|
||||
deposit_contract: None,
|
||||
base_fee_params: reth_chainspec::BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
|
||||
prune_delete_limit: 0,
|
||||
|
||||
@ -12,8 +12,8 @@ use reth_primitives::{
|
||||
keccak256,
|
||||
revm::env::fill_tx_env,
|
||||
revm_primitives::{CfgEnvWithHandlerCfg, EVMError, ExecutionResult, ResultAndState},
|
||||
Address, Block, BlockWithSenders, Bytes, Hardfork, Header, Receipt, TransactionSigned, TxType,
|
||||
B256, U256,
|
||||
Address, Block, BlockWithSenders, Bytes, EthereumHardfork, Header, Receipt, TransactionSigned,
|
||||
TxType, B256, U256,
|
||||
};
|
||||
use reth_revm::{
|
||||
db::{states::bundle_state::BundleRetention, BundleState},
|
||||
@ -69,16 +69,17 @@ fn construct_header(db: &Database, header: &RollupContract::BlockHeader) -> eyre
|
||||
let block_number = u64::try_from(header.sequence)?;
|
||||
|
||||
// Calculate base fee per gas for EIP-1559 transactions
|
||||
let base_fee_per_gas = if CHAIN_SPEC.fork(Hardfork::London).transitions_at_block(block_number) {
|
||||
constants::EIP1559_INITIAL_BASE_FEE
|
||||
} else {
|
||||
parent_block
|
||||
.as_ref()
|
||||
.ok_or(eyre::eyre!("parent block not found"))?
|
||||
.header
|
||||
.next_block_base_fee(CHAIN_SPEC.base_fee_params_at_block(block_number))
|
||||
.ok_or(eyre::eyre!("failed to calculate base fee"))?
|
||||
};
|
||||
let base_fee_per_gas =
|
||||
if CHAIN_SPEC.fork(EthereumHardfork::London).transitions_at_block(block_number) {
|
||||
constants::EIP1559_INITIAL_BASE_FEE
|
||||
} else {
|
||||
parent_block
|
||||
.as_ref()
|
||||
.ok_or(eyre::eyre!("parent block not found"))?
|
||||
.header
|
||||
.next_block_base_fee(CHAIN_SPEC.base_fee_params_at_block(block_number))
|
||||
.ok_or(eyre::eyre!("failed to calculate base fee"))?
|
||||
};
|
||||
|
||||
// Construct header
|
||||
Ok(Header {
|
||||
@ -103,7 +104,7 @@ fn configure_evm<'a>(
|
||||
.build(),
|
||||
);
|
||||
evm.db_mut().set_state_clear_flag(
|
||||
CHAIN_SPEC.fork(Hardfork::SpuriousDragon).active_at_block(header.number),
|
||||
CHAIN_SPEC.fork(EthereumHardfork::SpuriousDragon).active_at_block(header.number),
|
||||
);
|
||||
|
||||
let mut cfg = CfgEnvWithHandlerCfg::new_with_spec_id(evm.cfg().clone(), evm.spec_id());
|
||||
|
||||
@ -18,7 +18,7 @@ use reth_eth_wire::{
|
||||
};
|
||||
use reth_network::config::rng_secret_key;
|
||||
use reth_network_peers::{pk2id, NodeRecord};
|
||||
use reth_primitives::{Hardfork, Head, MAINNET_GENESIS_HASH};
|
||||
use reth_primitives::{EthereumHardfork, Head, MAINNET_GENESIS_HASH};
|
||||
use secp256k1::{SecretKey, SECP256K1};
|
||||
use tokio::net::TcpStream;
|
||||
|
||||
@ -95,14 +95,14 @@ async fn handshake_p2p(
|
||||
// Perform a ETH Wire handshake with a peer
|
||||
async fn handshake_eth(p2p_stream: AuthedP2PStream) -> eyre::Result<(AuthedEthStream, Status)> {
|
||||
let fork_filter = MAINNET.fork_filter(Head {
|
||||
timestamp: MAINNET.fork(Hardfork::Shanghai).as_timestamp().unwrap(),
|
||||
timestamp: MAINNET.fork(EthereumHardfork::Shanghai).as_timestamp().unwrap(),
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
let status = Status::builder()
|
||||
.chain(Chain::mainnet())
|
||||
.genesis(MAINNET_GENESIS_HASH)
|
||||
.forkid(MAINNET.hardfork_fork_id(Hardfork::Shanghai).unwrap())
|
||||
.forkid(MAINNET.hardfork_fork_id(EthereumHardfork::Shanghai).unwrap())
|
||||
.build();
|
||||
|
||||
let status = Status { version: p2p_stream.shared_capabilities().eth()?.version(), ..status };
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
use reth_chainspec::{BaseFeeParams, Chain, ChainSpec, ForkCondition, Hardfork};
|
||||
use reth_chainspec::{
|
||||
BaseFeeParams, Chain, ChainHardforks, ChainSpec, EthereumHardfork, ForkCondition,
|
||||
};
|
||||
use reth_discv4::NodeRecord;
|
||||
use reth_primitives::{b256, Head, B256};
|
||||
|
||||
use std::{collections::BTreeMap, sync::Arc};
|
||||
use std::sync::Arc;
|
||||
|
||||
const SHANGAI_BLOCK: u64 = 50523000;
|
||||
|
||||
@ -15,13 +17,13 @@ pub(crate) fn polygon_chain_spec() -> Arc<ChainSpec> {
|
||||
genesis: serde_json::from_str(include_str!("./genesis.json")).expect("deserialize genesis"),
|
||||
genesis_hash: Some(GENESIS),
|
||||
paris_block_and_final_difficulty: None,
|
||||
hardforks: BTreeMap::from([
|
||||
(Hardfork::Petersburg, ForkCondition::Block(0)),
|
||||
(Hardfork::Istanbul, ForkCondition::Block(3395000)),
|
||||
(Hardfork::MuirGlacier, ForkCondition::Block(3395000)),
|
||||
(Hardfork::Berlin, ForkCondition::Block(14750000)),
|
||||
(Hardfork::London, ForkCondition::Block(23850000)),
|
||||
(Hardfork::Shanghai, ForkCondition::Block(SHANGAI_BLOCK)),
|
||||
hardforks: ChainHardforks::new(vec![
|
||||
(EthereumHardfork::Petersburg.boxed(), ForkCondition::Block(0)),
|
||||
(EthereumHardfork::Istanbul.boxed(), ForkCondition::Block(3395000)),
|
||||
(EthereumHardfork::MuirGlacier.boxed(), ForkCondition::Block(3395000)),
|
||||
(EthereumHardfork::Berlin.boxed(), ForkCondition::Block(14750000)),
|
||||
(EthereumHardfork::London.boxed(), ForkCondition::Block(23850000)),
|
||||
(EthereumHardfork::Shanghai.boxed(), ForkCondition::Block(SHANGAI_BLOCK)),
|
||||
]),
|
||||
deposit_contract: None,
|
||||
base_fee_params: reth_chainspec::BaseFeeParamsKind::Constant(BaseFeeParams::ethereum()),
|
||||
|
||||
Reference in New Issue
Block a user