Skip to content

Commit

Permalink
chore: simplify revm specId mapping (#13553)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattsse authored Dec 27, 2024
1 parent 6049b6e commit d644900
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 160 deletions.
12 changes: 9 additions & 3 deletions crates/ethereum-forks/src/forkcondition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ impl ForkCondition {

/// Checks whether the fork condition is satisfied at the given block.
///
/// For TTD conditions, this will only return true if the activation block is already known.
/// This will return true if the block number is equal or greater than the activation block of:
/// - [`ForkCondition::Block`]
/// - [`ForkCondition::TTD`]
///
/// For timestamp conditions, this will always return false.
pub const fn active_at_block(&self, current_block: BlockNumber) -> bool {
Expand Down Expand Up @@ -83,6 +85,11 @@ impl ForkCondition {
matches!(self, Self::Timestamp(time) if timestamp >= *time && parent_timestamp < *time)
}

/// Checks whether the fork condition is satisfied at the given timestamp or number.
pub const fn active_at_timestamp_or_number(&self, timestamp: u64, block_number: u64) -> bool {
self.active_at_timestamp(timestamp) || self.active_at_block(block_number)
}

/// Checks whether the fork condition is satisfied at the given head block.
///
/// This will return true if:
Expand All @@ -91,8 +98,7 @@ impl ForkCondition {
/// - The condition is satisfied by the timestamp;
/// - or the condition is satisfied by the total difficulty
pub fn active_at_head(&self, head: &Head) -> bool {
self.active_at_block(head.number) ||
self.active_at_timestamp(head.timestamp) ||
self.active_at_timestamp_or_number(head.timestamp, head.number) ||
self.active_at_ttd(head.total_difficulty, head.difficulty)
}

Expand Down
2 changes: 1 addition & 1 deletion crates/ethereum-forks/src/hardforks/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ pub trait EthereumHardforks: Hardforks {
/// (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 { activation_block_number, .. } => {
Some(block_number >= activation_block_number)
}
ForkCondition::Block(paris_block) => Some(block_number >= paris_block),
_ => None,
}
}
Expand Down
179 changes: 111 additions & 68 deletions crates/ethereum/evm/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,56 +1,86 @@
use alloy_consensus::Header;
use reth_chainspec::{ChainSpec, EthereumHardforks};
use reth_ethereum_forks::{EthereumHardfork, Head};
use reth_ethereum_forks::EthereumHardfork;

/// Returns the revm [`SpecId`](revm_primitives::SpecId) at the given timestamp.
///
/// # Note
///
/// This is only intended to be used after the merge, when hardforks are activated by
/// timestamp.
pub fn revm_spec_by_timestamp_after_merge(
/// Map the latest active hardfork at the given header to a revm
/// [`SpecId`](revm_primitives::SpecId).
pub fn revm_spec(chain_spec: &ChainSpec, header: &Header) -> revm_primitives::SpecId {
revm_spec_by_timestamp_and_block_number(chain_spec, header.timestamp, header.number)
}

/// Map the latest active hardfork at the given timestamp or block number to a revm
/// [`SpecId`](revm_primitives::SpecId).
pub fn revm_spec_by_timestamp_and_block_number(
chain_spec: &ChainSpec,
timestamp: u64,
block_number: u64,
) -> revm_primitives::SpecId {
if chain_spec.is_osaka_active_at_timestamp(timestamp) {
if chain_spec
.fork(EthereumHardfork::Osaka)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::OSAKA
} else if chain_spec.is_prague_active_at_timestamp(timestamp) {
} else if chain_spec
.fork(EthereumHardfork::Prague)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::PRAGUE
} else if chain_spec.is_cancun_active_at_timestamp(timestamp) {
} else if chain_spec
.fork(EthereumHardfork::Cancun)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::CANCUN
} else if chain_spec.is_shanghai_active_at_timestamp(timestamp) {
} else if chain_spec
.fork(EthereumHardfork::Shanghai)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::SHANGHAI
} else {
} else if chain_spec.is_paris_active_at_block(block_number).is_some_and(|active| active) {
revm_primitives::MERGE
}
}

/// Map the latest active hardfork at the given block to a revm [`SpecId`](revm_primitives::SpecId).
pub fn revm_spec(chain_spec: &ChainSpec, block: &Head) -> revm_primitives::SpecId {
if chain_spec.fork(EthereumHardfork::Prague).active_at_head(block) {
revm_primitives::PRAGUE
} else if chain_spec.fork(EthereumHardfork::Cancun).active_at_head(block) {
revm_primitives::CANCUN
} else if chain_spec.fork(EthereumHardfork::Shanghai).active_at_head(block) {
revm_primitives::SHANGHAI
} else if chain_spec.is_paris_active_at_block(block.number).is_some_and(|active| active) {
revm_primitives::MERGE
} else if chain_spec.fork(EthereumHardfork::London).active_at_head(block) {
} else if chain_spec
.fork(EthereumHardfork::London)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::LONDON
} else if chain_spec.fork(EthereumHardfork::Berlin).active_at_head(block) {
} else if chain_spec
.fork(EthereumHardfork::Berlin)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::BERLIN
} else if chain_spec.fork(EthereumHardfork::Istanbul).active_at_head(block) {
} else if chain_spec
.fork(EthereumHardfork::Istanbul)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::ISTANBUL
} else if chain_spec.fork(EthereumHardfork::Petersburg).active_at_head(block) {
} else if chain_spec
.fork(EthereumHardfork::Petersburg)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::PETERSBURG
} else if chain_spec.fork(EthereumHardfork::Byzantium).active_at_head(block) {
} else if chain_spec
.fork(EthereumHardfork::Byzantium)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::BYZANTIUM
} else if chain_spec.fork(EthereumHardfork::SpuriousDragon).active_at_head(block) {
} else if chain_spec
.fork(EthereumHardfork::SpuriousDragon)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::SPURIOUS_DRAGON
} else if chain_spec.fork(EthereumHardfork::Tangerine).active_at_head(block) {
} else if chain_spec
.fork(EthereumHardfork::Tangerine)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::TANGERINE
} else if chain_spec.fork(EthereumHardfork::Homestead).active_at_head(block) {
} else if chain_spec
.fork(EthereumHardfork::Homestead)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::HOMESTEAD
} else if chain_spec.fork(EthereumHardfork::Frontier).active_at_head(block) {
} else if chain_spec
.fork(EthereumHardfork::Frontier)
.active_at_timestamp_or_number(timestamp, block_number)
{
revm_primitives::FRONTIER
} else {
panic!(
Expand All @@ -67,145 +97,158 @@ mod tests {
use reth_chainspec::{ChainSpecBuilder, MAINNET};

#[test]
fn test_revm_spec_by_timestamp_after_merge() {
fn test_revm_spec_by_timestamp() {
assert_eq!(
revm_spec_by_timestamp_after_merge(
revm_spec_by_timestamp_and_block_number(
&ChainSpecBuilder::mainnet().cancun_activated().build(),
0,
0
),
revm_primitives::CANCUN
);
assert_eq!(
revm_spec_by_timestamp_after_merge(
revm_spec_by_timestamp_and_block_number(
&ChainSpecBuilder::mainnet().shanghai_activated().build(),
0,
0
),
revm_primitives::SHANGHAI
);
let mainnet = ChainSpecBuilder::mainnet().build();
assert_eq!(
revm_spec_by_timestamp_after_merge(&ChainSpecBuilder::mainnet().build(), 0),
revm_spec_by_timestamp_and_block_number(&mainnet, 0, mainnet.paris_block().unwrap()),
revm_primitives::MERGE
);
}

#[test]
fn test_to_revm_spec() {
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().cancun_activated().build(), &Head::default()),
revm_spec(&ChainSpecBuilder::mainnet().cancun_activated().build(), &Default::default()),
revm_primitives::CANCUN
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().shanghai_activated().build(), &Head::default()),
revm_spec(
&ChainSpecBuilder::mainnet().shanghai_activated().build(),
&Default::default()
),
revm_primitives::SHANGHAI
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().paris_activated().build(), &Head::default()),
revm_spec(&ChainSpecBuilder::mainnet().paris_activated().build(), &Default::default()),
revm_primitives::MERGE
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().london_activated().build(), &Head::default()),
revm_spec(&ChainSpecBuilder::mainnet().london_activated().build(), &Default::default()),
revm_primitives::LONDON
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().berlin_activated().build(), &Head::default()),
revm_spec(&ChainSpecBuilder::mainnet().berlin_activated().build(), &Default::default()),
revm_primitives::BERLIN
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().istanbul_activated().build(), &Head::default()),
revm_spec(
&ChainSpecBuilder::mainnet().istanbul_activated().build(),
&Default::default()
),
revm_primitives::ISTANBUL
);
assert_eq!(
revm_spec(
&ChainSpecBuilder::mainnet().petersburg_activated().build(),
&Head::default()
&Default::default()
),
revm_primitives::PETERSBURG
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().byzantium_activated().build(), &Head::default()),
revm_spec(
&ChainSpecBuilder::mainnet().byzantium_activated().build(),
&Default::default()
),
revm_primitives::BYZANTIUM
);
assert_eq!(
revm_spec(
&ChainSpecBuilder::mainnet().spurious_dragon_activated().build(),
&Head::default()
&Default::default()
),
revm_primitives::SPURIOUS_DRAGON
);
assert_eq!(
revm_spec(
&ChainSpecBuilder::mainnet().tangerine_whistle_activated().build(),
&Head::default()
&Default::default()
),
revm_primitives::TANGERINE
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().homestead_activated().build(), &Head::default()),
revm_spec(
&ChainSpecBuilder::mainnet().homestead_activated().build(),
&Default::default()
),
revm_primitives::HOMESTEAD
);
assert_eq!(
revm_spec(&ChainSpecBuilder::mainnet().frontier_activated().build(), &Head::default()),
revm_spec(
&ChainSpecBuilder::mainnet().frontier_activated().build(),
&Default::default()
),
revm_primitives::FRONTIER
);
}

#[test]
fn test_eth_spec() {
assert_eq!(
revm_spec(&MAINNET, &Head { timestamp: 1710338135, ..Default::default() }),
revm_spec(&MAINNET, &Header { timestamp: 1710338135, ..Default::default() }),
revm_primitives::CANCUN
);
assert_eq!(
revm_spec(&MAINNET, &Head { timestamp: 1681338455, ..Default::default() }),
revm_spec(&MAINNET, &Header { timestamp: 1681338455, ..Default::default() }),
revm_primitives::SHANGHAI
);

assert_eq!(
revm_spec(
&MAINNET,
&Head {
total_difficulty: U256::from(58_750_000_000_000_000_000_010_u128),
difficulty: U256::from(10_u128),
number: 15537394,
..Default::default()
}
&Header { difficulty: U256::from(10_u128), number: 15537394, ..Default::default() }
),
revm_primitives::MERGE
);
assert_eq!(
revm_spec(&MAINNET, &Head { number: 15537394 - 10, ..Default::default() }),
revm_spec(&MAINNET, &Header { number: 15537394 - 10, ..Default::default() }),
revm_primitives::LONDON
);
assert_eq!(
revm_spec(&MAINNET, &Head { number: 12244000 + 10, ..Default::default() }),
revm_spec(&MAINNET, &Header { number: 12244000 + 10, ..Default::default() }),
revm_primitives::BERLIN
);
assert_eq!(
revm_spec(&MAINNET, &Head { number: 12244000 - 10, ..Default::default() }),
revm_spec(&MAINNET, &Header { number: 12244000 - 10, ..Default::default() }),
revm_primitives::ISTANBUL
);
assert_eq!(
revm_spec(&MAINNET, &Head { number: 7280000 + 10, ..Default::default() }),
revm_spec(&MAINNET, &Header { number: 7280000 + 10, ..Default::default() }),
revm_primitives::PETERSBURG
);
assert_eq!(
revm_spec(&MAINNET, &Head { number: 7280000 - 10, ..Default::default() }),
revm_spec(&MAINNET, &Header { number: 7280000 - 10, ..Default::default() }),
revm_primitives::BYZANTIUM
);
assert_eq!(
revm_spec(&MAINNET, &Head { number: 2675000 + 10, ..Default::default() }),
revm_spec(&MAINNET, &Header { number: 2675000 + 10, ..Default::default() }),
revm_primitives::SPURIOUS_DRAGON
);
assert_eq!(
revm_spec(&MAINNET, &Head { number: 2675000 - 10, ..Default::default() }),
revm_spec(&MAINNET, &Header { number: 2675000 - 10, ..Default::default() }),
revm_primitives::TANGERINE
);
assert_eq!(
revm_spec(&MAINNET, &Head { number: 1150000 + 10, ..Default::default() }),
revm_spec(&MAINNET, &Header { number: 1150000 + 10, ..Default::default() }),
revm_primitives::HOMESTEAD
);
assert_eq!(
revm_spec(&MAINNET, &Head { number: 1150000 - 10, ..Default::default() }),
revm_spec(&MAINNET, &Header { number: 1150000 - 10, ..Default::default() }),
revm_primitives::FRONTIER
);
}
Expand Down
Loading

0 comments on commit d644900

Please sign in to comment.