Skip to content

Commit

Permalink
feat(ethereum-forks): remove total difficulty for hardfork check (#13362
Browse files Browse the repository at this point in the history
)

Co-authored-by: Dan Cline <[email protected]>
  • Loading branch information
aroralanuk and Rjected authored Dec 20, 2024
1 parent dc6394b commit 82af170
Show file tree
Hide file tree
Showing 44 changed files with 383 additions and 647 deletions.
2 changes: 1 addition & 1 deletion bin/reth/src/commands/debug_cmd/build_block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db);

let block_execution_output =
executor.execute((&block_with_senders.clone().unseal(), U256::MAX).into())?;
executor.execute(&block_with_senders.clone().unseal())?;
let execution_outcome =
ExecutionOutcome::from((block_execution_output, block.number));
debug!(target: "reth::cli", ?execution_outcome, "Executed block");
Expand Down
22 changes: 7 additions & 15 deletions bin/reth/src/commands/debug_cmd/in_memory_merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ use reth_node_ethereum::EthExecutorProvider;
use reth_primitives::BlockExt;
use reth_provider::{
providers::ProviderNodeTypes, AccountExtReader, ChainSpecProvider, DatabaseProviderFactory,
HashedPostStateProvider, HashingWriter, HeaderProvider, LatestStateProviderRef,
OriginalValuesKnown, ProviderFactory, StageCheckpointReader, StateWriter, StorageLocation,
StorageReader,
HashedPostStateProvider, HashingWriter, LatestStateProviderRef, OriginalValuesKnown,
ProviderFactory, StageCheckpointReader, StateWriter, StorageLocation, StorageReader,
};
use reth_revm::database::StateProviderDatabase;
use reth_stages::StageId;
Expand Down Expand Up @@ -148,19 +147,12 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
let db = StateProviderDatabase::new(&state_provider);

let executor = EthExecutorProvider::ethereum(provider_factory.chain_spec()).executor(db);

let merkle_block_td =
provider.header_td_by_number(merkle_block_number)?.unwrap_or_default();
let block_execution_output = executor.execute(
(
&block
.clone()
.unseal::<BlockTy<N>>()
.with_recovered_senders()
.ok_or(BlockValidationError::SenderRecoveryError)?,
merkle_block_td + block.difficulty,
)
.into(),
&block
.clone()
.unseal::<BlockTy<N>>()
.with_recovered_senders()
.ok_or(BlockValidationError::SenderRecoveryError)?,
)?;
let execution_outcome = ExecutionOutcome::from((block_execution_output, block.number));

Expand Down
2 changes: 1 addition & 1 deletion bin/reth/src/commands/debug_cmd/merkle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl<C: ChainSpecParser<ChainSpec = ChainSpec>> Command<C> {
let mut executor = executor_provider.batch_executor(StateProviderDatabase::new(
LatestStateProviderRef::new(&provider_rw),
));
executor.execute_and_verify_one((&sealed_block.clone().unseal(), td).into())?;
executor.execute_and_verify_one(&sealed_block.clone().unseal())?;
let execution_outcome = executor.finalize();

provider_rw.write_state(
Expand Down
2 changes: 1 addition & 1 deletion crates/blockchain-tree/src/blockchain_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,6 @@ where
.header_td(&block.parent_hash)?
.ok_or_else(|| BlockchainTreeError::CanonicalChain { block_hash: block.parent_hash })?;

// Pass the parent total difficulty to short-circuit unnecessary calculations.
if !self
.externals
.provider_factory
Expand Down Expand Up @@ -1037,6 +1036,7 @@ where
})
},
)?;

if !self
.externals
.provider_factory
Expand Down
4 changes: 2 additions & 2 deletions crates/blockchain-tree/src/chain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
use super::externals::TreeExternals;
use crate::BundleStateDataRef;
use alloy_eips::ForkBlock;
use alloy_primitives::{BlockHash, BlockNumber, U256};
use alloy_primitives::{BlockHash, BlockNumber};
use reth_blockchain_tree_api::{
error::{BlockchainTreeError, InsertBlockErrorKind},
BlockAttachment, BlockValidationKind,
Expand Down Expand Up @@ -209,7 +209,7 @@ impl AppendableChain {
let block_hash = block.hash();
let block = block.unseal();

let state = executor.execute((&block, U256::MAX).into())?;
let state = executor.execute(&block)?;
externals.consensus.validate_block_post_execution(
&block,
PostExecutionInput::new(&state.receipts, &state.requests),
Expand Down
34 changes: 27 additions & 7 deletions crates/chainspec/src/spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,12 @@ impl ChainSpec {
self.chain == Chain::optimism_mainnet()
}

/// Returns the known paris block, if it exists.
#[inline]
pub fn paris_block(&self) -> Option<u64> {
self.paris_block_and_final_difficulty.map(|(block, _)| block)
}

/// Get the genesis block specification.
///
/// To get the header for the genesis block, use [`Self::genesis_header`] instead.
Expand Down Expand Up @@ -389,7 +395,7 @@ impl ChainSpec {

/// Returns the hardfork display helper.
pub fn display_hardforks(&self) -> DisplayHardforks {
DisplayHardforks::new(&self, self.paris_block_and_final_difficulty.map(|(block, _)| block))
DisplayHardforks::new(&self)
}

/// Get the fork id for the given hardfork.
Expand Down Expand Up @@ -603,12 +609,20 @@ impl From<Genesis> for ChainSpec {
.filter_map(|(hardfork, opt)| opt.map(|block| (hardfork, ForkCondition::Block(block))))
.collect::<Vec<_>>();

// Paris
// We expect no new networks to be configured with the merge, so we ignore the TTD field
// and merge netsplit block from external genesis files. All existing networks that have
// merged should have a static ChainSpec already (namely mainnet and sepolia).
let paris_block_and_final_difficulty =
if let Some(ttd) = genesis.config.terminal_total_difficulty {
hardforks.push((
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD {
// NOTE: this will not work properly if the merge is not activated at
// genesis, and there is no merge netsplit block
activation_block_number: genesis
.config
.merge_netsplit_block
.unwrap_or_default(),
total_difficulty: ttd,
fork_block: genesis.config.merge_netsplit_block,
},
Expand Down Expand Up @@ -765,10 +779,10 @@ impl ChainSpecBuilder {
/// Enable the Paris hardfork at the given TTD.
///
/// Does not set the merge netsplit block.
pub fn paris_at_ttd(self, ttd: U256) -> Self {
pub fn paris_at_ttd(self, ttd: U256, activation_block_number: BlockNumber) -> Self {
self.with_fork(
EthereumHardfork::Paris,
ForkCondition::TTD { total_difficulty: ttd, fork_block: None },
ForkCondition::TTD { activation_block_number, total_difficulty: ttd, fork_block: None },
)
}

Expand Down Expand Up @@ -846,7 +860,11 @@ impl ChainSpecBuilder {
self = self.london_activated();
self.hardforks.insert(
EthereumHardfork::Paris,
ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO },
ForkCondition::TTD {
activation_block_number: 0,
total_difficulty: U256::ZERO,
fork_block: None,
},
);
self
}
Expand Down Expand Up @@ -888,8 +906,8 @@ impl ChainSpecBuilder {
pub fn build(self) -> ChainSpec {
let paris_block_and_final_difficulty = {
self.hardforks.get(EthereumHardfork::Paris).and_then(|cond| {
if let ForkCondition::TTD { fork_block, total_difficulty } = cond {
fork_block.map(|fork_block| (fork_block, total_difficulty))
if let ForkCondition::TTD { total_difficulty, activation_block_number, .. } = cond {
Some((activation_block_number, total_difficulty))
} else {
None
}
Expand Down Expand Up @@ -1133,6 +1151,7 @@ Post-merge hard forks (timestamp based):
.with_fork(
EthereumHardfork::Paris,
ForkCondition::TTD {
activation_block_number: 101,
fork_block: Some(101),
total_difficulty: U256::from(10_790_000),
},
Expand Down Expand Up @@ -1166,6 +1185,7 @@ Post-merge hard forks (timestamp based):
// Fork::ConditionTTD test case without a new chain spec to demonstrate ChainSpec::satisfy
// is independent of ChainSpec for this(these - including ForkCondition::Block) match arm(s)
let fork_cond_ttd_no_new_spec = fork_cond_block_only_case.satisfy(ForkCondition::TTD {
activation_block_number: 101,
fork_block: None,
total_difficulty: U256::from(10_790_000),
});
Expand Down
2 changes: 1 addition & 1 deletion crates/consensus/beacon/src/engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2460,7 +2460,7 @@ mod tests {
.chain(MAINNET.chain)
.genesis(MAINNET.genesis.clone())
.london_activated()
.paris_at_ttd(U256::from(3))
.paris_at_ttd(U256::from(3), 3)
.build(),
);

Expand Down
24 changes: 10 additions & 14 deletions crates/consensus/common/src/calc.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use alloy_consensus::constants::ETH_TO_WEI;
use alloy_primitives::{BlockNumber, U256};
use reth_chainspec::{EthereumHardfork, Hardforks};
use alloy_primitives::BlockNumber;
use reth_chainspec::{EthereumHardfork, EthereumHardforks, Hardforks};

/// Calculates the base block reward.
///
Expand All @@ -21,13 +21,11 @@ use reth_chainspec::{EthereumHardfork, Hardforks};
/// - Definition: [Yellow Paper][yp] (page 15, 11.3)
///
/// [yp]: https://ethereum.github.io/yellowpaper/paper.pdf
pub fn base_block_reward(
chain_spec: impl Hardforks,
pub fn base_block_reward<ChainSpec: EthereumHardforks>(
chain_spec: &ChainSpec,
block_number: BlockNumber,
block_difficulty: U256,
total_difficulty: U256,
) -> Option<u128> {
if chain_spec.fork(EthereumHardfork::Paris).active_at_ttd(total_difficulty, block_difficulty) {
if chain_spec.is_paris_active_at_block(block_number).is_some_and(|active| active) {
None
} else {
Some(base_block_reward_pre_merge(chain_spec, block_number))
Expand Down Expand Up @@ -62,12 +60,9 @@ pub fn base_block_reward_pre_merge(chain_spec: impl Hardforks, block_number: Blo
/// #
/// // This is block 126 on mainnet.
/// let block_number = 126;
/// let block_difficulty = U256::from(18_145_285_642usize);
/// let total_difficulty = U256::from(2_235_668_675_900usize);
/// let number_of_ommers = 1;
///
/// let reward = base_block_reward(&*MAINNET, block_number, block_difficulty, total_difficulty)
/// .map(|reward| block_reward(reward, 1));
/// let reward = base_block_reward(&*MAINNET, block_number).map(|reward| block_reward(reward, 1));
///
/// // The base block reward is 5 ETH, and the ommer inclusion reward is 1/32th of 5 ETH.
/// assert_eq!(reward.unwrap(), ETH_TO_WEI * 5 + ((ETH_TO_WEI * 5) >> 5));
Expand Down Expand Up @@ -113,6 +108,7 @@ pub const fn ommer_reward(
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::U256;
use reth_chainspec::MAINNET;

#[test]
Expand All @@ -126,11 +122,11 @@ mod tests {
// Petersburg
((7280000, U256::ZERO), Some(ETH_TO_WEI * 2)),
// Merge
((10000000, U256::from(58_750_000_000_000_000_000_000_u128)), None),
((15537394, U256::from(58_750_000_000_000_000_000_000_u128)), None),
];

for ((block_number, td), expected_reward) in cases {
assert_eq!(base_block_reward(&*MAINNET, block_number, U256::ZERO, td), expected_reward);
for ((block_number, _td), expected_reward) in cases {
assert_eq!(base_block_reward(&*MAINNET, block_number), expected_reward);
}
}

Expand Down
5 changes: 2 additions & 3 deletions crates/engine/invalid-block-hooks/src/witness.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use alloy_consensus::BlockHeader;
use alloy_primitives::{keccak256, B256, U256};
use alloy_primitives::{keccak256, B256};
use alloy_rpc_types_debug::ExecutionWitness;
use eyre::OptionExt;
use pretty_assertions::Comparison;
Expand Down Expand Up @@ -79,7 +79,7 @@ where

// Setup environment for the execution.
let EvmEnv { cfg_env_with_handler_cfg, block_env } =
self.evm_config.cfg_and_block_env(block.header(), U256::MAX);
self.evm_config.cfg_and_block_env(block.header());

// Setup EVM
let mut evm = self.evm_config.evm_with_env(
Expand Down Expand Up @@ -116,7 +116,6 @@ where
let balance_increments = post_block_balance_increments(
self.provider.chain_spec().as_ref(),
&block.clone().unseal().block,
U256::MAX,
);

// increment balances
Expand Down
6 changes: 1 addition & 5 deletions crates/engine/tree/src/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2261,11 +2261,7 @@ where
// };
let state_hook = Box::new(|_state: &EvmState| {});

let output = self.metrics.executor.execute_metered(
executor,
(&block, U256::MAX).into(),
state_hook,
)?;
let output = self.metrics.executor.execute_metered(executor, &block, state_hook)?;

trace!(target: "engine::tree", elapsed=?exec_time.elapsed(), ?block_number, "Executed block");

Expand Down
3 changes: 1 addition & 2 deletions crates/engine/util/src/reorg.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! Stream wrapper that simulates reorgs.
use alloy_consensus::{Header, Transaction};
use alloy_primitives::U256;
use alloy_rpc_types_engine::{
CancunPayloadFields, ExecutionPayload, ExecutionPayloadSidecar, ForkchoiceState, PayloadStatus,
};
Expand Down Expand Up @@ -299,7 +298,7 @@ where

// Configure environments
let EvmEnv { cfg_env_with_handler_cfg, block_env } =
evm_config.cfg_and_block_env(&reorg_target.header, U256::MAX);
evm_config.cfg_and_block_env(&reorg_target.header);
let env = EnvWithHandlerCfg::new_with_cfg_env(
cfg_env_with_handler_cfg,
block_env,
Expand Down
24 changes: 11 additions & 13 deletions crates/ethereum-forks/src/display.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,12 @@ impl core::fmt::Display for DisplayFork {
ForkCondition::Block(at) | ForkCondition::Timestamp(at) => {
write!(f, "{name_with_eip:32} @{at}")?;
}
ForkCondition::TTD { fork_block, total_difficulty } => {
ForkCondition::TTD { total_difficulty, .. } => {
// All networks that have merged are finalized.
write!(
f,
"{:32} @{} ({})",
name_with_eip,
total_difficulty,
if fork_block.is_some() {
"network is known to be merged"
} else {
"network is not known to be merged"
}
"{:32} @{} (network is known to be merged)",
name_with_eip, total_difficulty,
)?;
}
ForkCondition::Never => unreachable!(),
Expand Down Expand Up @@ -141,7 +136,7 @@ impl core::fmt::Display for DisplayHardforks {

impl DisplayHardforks {
/// Creates a new [`DisplayHardforks`] from an iterator of hardforks.
pub fn new<H: Hardforks>(hardforks: &H, known_paris_block: Option<u64>) -> Self {
pub fn new<H: Hardforks>(hardforks: &H) -> Self {
let mut pre_merge = Vec::new();
let mut with_merge = Vec::new();
let mut post_merge = Vec::new();
Expand All @@ -154,9 +149,12 @@ impl DisplayHardforks {
ForkCondition::Block(_) => {
pre_merge.push(display_fork);
}
ForkCondition::TTD { total_difficulty, .. } => {
display_fork.activated_at =
ForkCondition::TTD { fork_block: known_paris_block, total_difficulty };
ForkCondition::TTD { activation_block_number, total_difficulty, fork_block } => {
display_fork.activated_at = ForkCondition::TTD {
activation_block_number,
fork_block,
total_difficulty,
};
with_merge.push(display_fork);
}
ForkCondition::Timestamp(_) => {
Expand Down
Loading

0 comments on commit 82af170

Please sign in to comment.