feat(ethereum-forks): remove total difficulty for hardfork check (#13362)

Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com>
This commit is contained in:
Kunal Arora
2024-12-20 20:58:05 +05:30
committed by GitHub
parent dc6394b05b
commit 82af170687
44 changed files with 382 additions and 646 deletions

View File

@@ -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");

View File

@@ -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;
@@ -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));

View File

@@ -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(

View File

@@ -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
@@ -1037,6 +1036,7 @@ where
})
},
)?;
if !self
.externals
.provider_factory

View File

@@ -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,
@@ -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),

View File

@@ -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.
@@ -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.
@@ -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,
},
@@ -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 },
)
}
@@ -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
}
@@ -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
}
@@ -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),
},
@@ -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),
});

View File

@@ -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(),
);

View File

@@ -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.
///
@@ -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))
@@ -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));
@@ -113,6 +108,7 @@ pub const fn ommer_reward(
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::U256;
use reth_chainspec::MAINNET;
#[test]
@@ -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);
}
}

View File

@@ -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;
@@ -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(
@@ -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

View File

@@ -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");

View File

@@ -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,
};
@@ -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,

View File

@@ -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!(),
@@ -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();
@@ -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(_) => {

View File

@@ -9,6 +9,12 @@ pub enum ForkCondition {
Block(BlockNumber),
/// The fork is activated after a total difficulty has been reached.
TTD {
/// The activation block number for the merge.
///
/// This should represent the first post-merge block for the given network. Sepolia and
/// mainnet are the only networks that have merged, and they have both finalized
/// post-merge, so total difficulty is effectively deprecated.
activation_block_number: BlockNumber,
/// The block number at which TTD is reached, if it is known.
///
/// This should **NOT** be set unless you want this block advertised as [EIP-2124][eip2124]
@@ -127,16 +133,22 @@ mod tests {
);
// Test if TTD-based condition with known block activates
let fork_condition =
ForkCondition::TTD { fork_block: Some(10), total_difficulty: U256::from(1000) };
let fork_condition = ForkCondition::TTD {
activation_block_number: 10,
fork_block: Some(10),
total_difficulty: U256::from(1000),
};
assert!(
fork_condition.active_at_block(10),
"The TTD condition should be active at block 10"
);
// Test if TTD-based condition with unknown block does not activate
let fork_condition =
ForkCondition::TTD { fork_block: None, total_difficulty: U256::from(1000) };
let fork_condition = ForkCondition::TTD {
activation_block_number: 10,
fork_block: None,
total_difficulty: U256::from(1000),
};
assert!(
!fork_condition.active_at_block(10),
"The TTD condition should not be active at block 10 with an unknown block number"
@@ -166,8 +178,11 @@ mod tests {
#[test]
fn test_active_at_ttd() {
// Test if the condition activates at the correct total difficulty
let fork_condition =
ForkCondition::TTD { fork_block: Some(10), total_difficulty: U256::from(1000) };
let fork_condition = ForkCondition::TTD {
activation_block_number: 10,
fork_block: Some(10),
total_difficulty: U256::from(1000),
};
assert!(
fork_condition.active_at_ttd(U256::from(1000000), U256::from(100)),
"The TTD condition should be active when the total difficulty matches"
@@ -258,26 +273,38 @@ mod tests {
);
// Test if the condition activates based on total difficulty and block number
let fork_condition =
ForkCondition::TTD { fork_block: Some(9), total_difficulty: U256::from(900) };
let fork_condition = ForkCondition::TTD {
activation_block_number: 10,
fork_block: Some(9),
total_difficulty: U256::from(900),
};
assert!(
fork_condition.active_at_head(&head),
"The condition should be active at the given head total difficulty"
);
let fork_condition =
ForkCondition::TTD { fork_block: None, total_difficulty: U256::from(900) };
let fork_condition = ForkCondition::TTD {
activation_block_number: 10,
fork_block: None,
total_difficulty: U256::from(900),
};
assert!(
fork_condition.active_at_head(&head),
"The condition should be active at the given head total difficulty as the block number is unknown"
);
let fork_condition =
ForkCondition::TTD { fork_block: Some(11), total_difficulty: U256::from(900) };
let fork_condition = ForkCondition::TTD {
activation_block_number: 10,
fork_block: Some(11),
total_difficulty: U256::from(900),
};
assert!(
fork_condition.active_at_head(&head),
"The condition should be active as the total difficulty is higher"
);
let fork_condition =
ForkCondition::TTD { fork_block: Some(10), total_difficulty: U256::from(9000) };
let fork_condition = ForkCondition::TTD {
activation_block_number: 10,
fork_block: Some(10),
total_difficulty: U256::from(9000),
};
assert!(
fork_condition.active_at_head(&head),
"The condition should be active as the total difficulty is higher than head"

View File

@@ -26,7 +26,11 @@ pub static DEV_HARDFORKS: LazyLock<ChainHardforks> = LazyLock::new(|| {
(EthereumHardfork::London.boxed(), ForkCondition::Block(0)),
(
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD { fork_block: None, total_difficulty: U256::ZERO },
ForkCondition::TTD {
activation_block_number: 0,
fork_block: None,
total_difficulty: U256::ZERO,
},
),
(EthereumHardfork::Shanghai.boxed(), ForkCondition::Timestamp(0)),
(EthereumHardfork::Cancun.boxed(), ForkCondition::Timestamp(0)),

View File

@@ -352,6 +352,7 @@ impl EthereumHardfork {
(
Self::Paris,
ForkCondition::TTD {
activation_block_number: 15537394,
fork_block: None,
total_difficulty: uint!(58_750_000_000_000_000_000_000_U256),
},
@@ -379,6 +380,7 @@ impl EthereumHardfork {
(
Self::Paris,
ForkCondition::TTD {
activation_block_number: 1735371,
fork_block: Some(1735371),
total_difficulty: uint!(17_000_000_000_000_000_U256),
},
@@ -403,7 +405,14 @@ impl EthereumHardfork {
(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::Paris,
ForkCondition::TTD {
activation_block_number: 0,
fork_block: Some(0),
total_difficulty: U256::ZERO,
},
),
(Self::Shanghai, ForkCondition::Timestamp(1696000704)),
(Self::Cancun, ForkCondition::Timestamp(1707305664)),
]

View File

@@ -50,8 +50,8 @@ pub trait EthereumHardforks: Hardforks {
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)
ForkCondition::TTD { activation_block_number, .. } => {
Some(block_number >= activation_block_number)
}
_ => None,
}

View File

@@ -23,6 +23,7 @@ pub struct Head {
/// The timestamp of the head block.
pub timestamp: u64,
}
impl Head {
/// Creates a new `Head` instance.
pub const fn new(

View File

@@ -32,7 +32,7 @@ pub fn revm_spec(chain_spec: &ChainSpec, block: &Head) -> revm_primitives::SpecI
revm_primitives::CANCUN
} else if chain_spec.fork(EthereumHardfork::Shanghai).active_at_head(block) {
revm_primitives::SHANGHAI
} else if chain_spec.fork(EthereumHardfork::Paris).active_at_head(block) {
} 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) {
revm_primitives::LONDON
@@ -166,19 +166,7 @@ mod tests {
&Head {
total_difficulty: U256::from(58_750_000_000_000_000_000_010_u128),
difficulty: U256::from(10_u128),
..Default::default()
}
),
revm_primitives::MERGE
);
// TTD trumps the block number
assert_eq!(
revm_spec(
&MAINNET,
&Head {
number: 15537394 - 10,
total_difficulty: U256::from(58_750_000_000_000_000_000_010_u128),
difficulty: U256::from(10_u128),
number: 15537394,
..Default::default()
}
),

View File

@@ -26,7 +26,7 @@ use reth_primitives::{BlockWithSenders, EthPrimitives, Receipt};
use reth_revm::db::State;
use revm_primitives::{
db::{Database, DatabaseCommit},
EnvWithHandlerCfg, ResultAndState, U256,
EnvWithHandlerCfg, ResultAndState,
};
/// Factory for [`EthExecutionStrategy`].
@@ -123,13 +123,9 @@ where
/// # Caution
///
/// This does not initialize the tx environment.
fn evm_env_for_block(
&self,
header: &alloy_consensus::Header,
total_difficulty: U256,
) -> EnvWithHandlerCfg {
fn evm_env_for_block(&self, header: &alloy_consensus::Header) -> EnvWithHandlerCfg {
let EvmEnv { cfg_env_with_handler_cfg, block_env } =
self.evm_config.cfg_and_block_env(header, total_difficulty);
self.evm_config.cfg_and_block_env(header);
EnvWithHandlerCfg::new_with_cfg_env(cfg_env_with_handler_cfg, block_env, Default::default())
}
}
@@ -151,17 +147,13 @@ where
self.tx_env_overrides = Some(tx_env_overrides);
}
fn apply_pre_execution_changes(
&mut self,
block: &BlockWithSenders,
total_difficulty: U256,
) -> Result<(), Self::Error> {
fn apply_pre_execution_changes(&mut self, block: &BlockWithSenders) -> Result<(), Self::Error> {
// Set state clear flag if the block is after the Spurious Dragon hardfork.
let state_clear_flag =
(*self.chain_spec).is_spurious_dragon_active_at_block(block.header.number);
self.state.set_state_clear_flag(state_clear_flag);
let env = self.evm_env_for_block(&block.header, total_difficulty);
let env = self.evm_env_for_block(&block.header);
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
self.system_caller.apply_pre_execution_changes(&block.block, &mut evm)?;
@@ -172,9 +164,8 @@ where
fn execute_transactions(
&mut self,
block: &BlockWithSenders,
total_difficulty: U256,
) -> Result<ExecuteOutput<Receipt>, Self::Error> {
let env = self.evm_env_for_block(&block.header, total_difficulty);
let env = self.evm_env_for_block(&block.header);
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
let mut cumulative_gas_used = 0;
@@ -234,10 +225,9 @@ where
fn apply_post_execution_changes(
&mut self,
block: &BlockWithSenders,
total_difficulty: U256,
receipts: &[Receipt],
) -> Result<Requests, Self::Error> {
let env = self.evm_env_for_block(&block.header, total_difficulty);
let env = self.evm_env_for_block(&block.header);
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
let requests = if self.chain_spec.is_prague_active_at_timestamp(block.timestamp) {
@@ -258,8 +248,7 @@ where
};
drop(evm);
let mut balance_increments =
post_block_balance_increments(&self.chain_spec, &block.block, total_difficulty);
let mut balance_increments = post_block_balance_increments(&self.chain_spec, &block.block);
// Irregular state change at Ethereum DAO hardfork
if self.chain_spec.fork(EthereumHardfork::Dao).transitions_at_block(block.number) {
@@ -337,7 +326,7 @@ mod tests {
eip7002::{WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS, WITHDRAWAL_REQUEST_PREDEPLOY_CODE},
eip7685::EMPTY_REQUESTS_HASH,
};
use alloy_primitives::{b256, fixed_bytes, keccak256, Bytes, TxKind, B256};
use alloy_primitives::{b256, fixed_bytes, keccak256, Bytes, TxKind, B256, U256};
use reth_chainspec::{ChainSpecBuilder, ForkCondition};
use reth_evm::execute::{
BasicBlockExecutorProvider, BatchExecutor, BlockExecutorProvider, Executor,
@@ -421,23 +410,13 @@ mod tests {
// attempt to execute a block without parent beacon block root, expect err
let err = executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block {
header: header.clone(),
body: BlockBody {
transactions: vec![],
ommers: vec![],
withdrawals: None,
},
},
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block {
header: header.clone(),
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
},
vec![],
))
.expect_err(
"Executing cancun block without parent beacon block root field should fail",
);
@@ -452,23 +431,13 @@ mod tests {
// Now execute a block with the fixed header, ensure that it does not fail
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block {
header: header.clone(),
body: BlockBody {
transactions: vec![],
ommers: vec![],
withdrawals: None,
},
},
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block {
header: header.clone(),
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
},
vec![],
))
.unwrap();
// check the actual storage of the contract - it should be:
@@ -522,23 +491,13 @@ mod tests {
// attempt to execute an empty block with parent beacon block root, this should not fail
provider
.batch_executor(StateProviderDatabase::new(&db))
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block {
header,
body: BlockBody {
transactions: vec![],
ommers: vec![],
withdrawals: None,
},
},
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block {
header,
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
},
vec![],
))
.expect(
"Executing a block with no transactions while cancun is active should not fail",
);
@@ -576,23 +535,13 @@ mod tests {
// attempt to execute an empty block with parent beacon block root, this should not fail
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block {
header,
body: BlockBody {
transactions: vec![],
ommers: vec![],
withdrawals: None,
},
},
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block {
header,
body: BlockBody { transactions: vec![], ommers: vec![], withdrawals: None },
},
vec![],
))
.expect(
"Executing a block with no transactions while cancun is active should not fail",
);
@@ -622,16 +571,10 @@ mod tests {
// attempt to execute the genesis block with non-zero parent beacon block root, expect err
header.parent_beacon_block_root = Some(B256::with_last_byte(0x69));
let _err = executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header: header.clone(), body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header: header.clone(), body: Default::default() },
vec![],
))
.expect_err(
"Executing genesis cancun block with non-zero parent beacon block root field
should fail",
@@ -643,16 +586,10 @@ mod tests {
// now try to process the genesis block again, this time ensuring that a system contract
// call does not occur
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
))
.unwrap();
// there is no system contract call so there should be NO STORAGE CHANGES
@@ -697,16 +634,10 @@ mod tests {
// Now execute a block with the fixed header, ensure that it does not fail
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header: header.clone(), body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header: header.clone(), body: Default::default() },
vec![],
))
.unwrap();
// check the actual storage of the contract - it should be:
@@ -773,16 +704,10 @@ mod tests {
// attempt to execute an empty block, this should not fail
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
))
.expect(
"Executing a block with no transactions while Prague is active should not fail",
);
@@ -816,16 +741,10 @@ mod tests {
// attempt to execute genesis block, this should not fail
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
))
.expect(
"Executing a block with no transactions while Prague is active should not fail",
);
@@ -866,16 +785,10 @@ mod tests {
// attempt to execute the fork activation block, this should not fail
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
))
.expect(
"Executing a block with no transactions while Prague is active should not fail",
);
@@ -922,16 +835,10 @@ mod tests {
// attempt to execute the fork activation block, this should not fail
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
))
.expect(
"Executing a block with no transactions while Prague is active should not fail",
);
@@ -970,16 +877,10 @@ mod tests {
// attempt to execute the genesis block, this should not fail
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
))
.expect(
"Executing a block with no transactions while Prague is active should not fail",
);
@@ -1005,16 +906,10 @@ mod tests {
let header_hash = header.hash_slow();
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
))
.expect(
"Executing a block with no transactions while Prague is active should not fail",
);
@@ -1043,16 +938,10 @@ mod tests {
};
executor
.execute_and_verify_one(
(
&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
),
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders::new_unchecked(
Block { header, body: Default::default() },
vec![],
))
.expect(
"Executing a block with no transactions while Prague is active should not fail",
);
@@ -1133,16 +1022,9 @@ mod tests {
let BlockExecutionOutput { receipts, requests, .. } = executor
.execute(
(
&Block {
header,
body: BlockBody { transactions: vec![tx], ..Default::default() },
}
&Block { header, body: BlockBody { transactions: vec![tx], ..Default::default() } }
.with_recovered_senders()
.unwrap(),
U256::ZERO,
)
.into(),
)
.unwrap();
@@ -1216,13 +1098,9 @@ mod tests {
// Execute the block and capture the result
let exec_result = executor.execute(
(
&Block { header, body: BlockBody { transactions: vec![tx], ..Default::default() } }
.with_recovered_senders()
.unwrap(),
U256::ZERO,
)
.into(),
&Block { header, body: BlockBody { transactions: vec![tx], ..Default::default() } }
.with_recovered_senders()
.unwrap(),
);
// Check if the execution result is an error and assert the specific error type
@@ -1282,7 +1160,7 @@ mod tests {
let tx_clone = tx.clone();
let _output = executor
.execute_with_state_hook((block, U256::ZERO).into(), move |state: &EvmState| {
.execute_with_state_hook(block, move |state: &EvmState| {
if let Some(account) = state.get(&withdrawal_recipient) {
let _ = tx_clone.send(account.info.balance);
}

View File

@@ -109,19 +109,15 @@ impl ConfigureEvmEnv for EthEvmConfig {
env.block.basefee = U256::ZERO;
}
fn fill_cfg_env(
&self,
cfg_env: &mut CfgEnvWithHandlerCfg,
header: &Header,
total_difficulty: U256,
) {
fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Header) {
let spec_id = config::revm_spec(
self.chain_spec(),
&Head {
number: header.number,
timestamp: header.timestamp,
difficulty: header.difficulty,
total_difficulty,
// NOTE: this does nothing within revm_spec
total_difficulty: U256::MIN,
hash: Default::default(),
},
);
@@ -226,14 +222,10 @@ mod tests {
.shanghai_activated()
.build();
// Define the total difficulty as zero (default)
let total_difficulty = U256::ZERO;
// Use the `EthEvmConfig` to fill the `cfg_env` and `block_env` based on the ChainSpec,
// Header, and total difficulty
let EvmEnv { cfg_env_with_handler_cfg, .. } =
EthEvmConfig::new(Arc::new(chain_spec.clone()))
.cfg_and_block_env(&header, total_difficulty);
EthEvmConfig::new(Arc::new(chain_spec.clone())).cfg_and_block_env(&header);
// Assert that the chain ID in the `cfg_env` is correctly set to the chain ID of the
// ChainSpec

View File

@@ -1,29 +1,6 @@
use alloy_eips::eip7685::Requests;
use alloy_primitives::U256;
use revm::db::BundleState;
/// A helper type for ethereum block inputs that consists of a block and the total difficulty.
#[derive(Debug)]
pub struct BlockExecutionInput<'a, Block> {
/// The block to execute.
pub block: &'a Block,
/// The total difficulty of the block.
pub total_difficulty: U256,
}
impl<'a, Block> BlockExecutionInput<'a, Block> {
/// Creates a new input.
pub const fn new(block: &'a Block, total_difficulty: U256) -> Self {
Self { block, total_difficulty }
}
}
impl<'a, Block> From<(&'a Block, U256)> for BlockExecutionInput<'a, Block> {
fn from((block, total_difficulty): (&'a Block, U256)) -> Self {
Self::new(block, total_difficulty)
}
}
/// The output of an ethereum block.
///
/// Contains the state changes, transaction receipts, and total gas used in the block.

View File

@@ -5,7 +5,7 @@ use alloy_consensus::BlockHeader;
pub use reth_execution_errors::{
BlockExecutionError, BlockValidationError, InternalBlockExecutionError,
};
pub use reth_execution_types::{BlockExecutionInput, BlockExecutionOutput, ExecutionOutcome};
pub use reth_execution_types::{BlockExecutionOutput, ExecutionOutcome};
use reth_primitives_traits::Block as _;
pub use reth_storage_errors::provider::ProviderError;
@@ -25,7 +25,7 @@ use revm::{
db::{states::bundle_state::BundleRetention, BundleState},
State,
};
use revm_primitives::{db::Database, Account, AccountStatus, EvmState, U256};
use revm_primitives::{db::Database, Account, AccountStatus, EvmState};
/// A general purpose executor trait that executes an input (e.g. block) and produces an output
/// (e.g. state changes and receipts).
@@ -151,10 +151,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static {
/// the returned state.
type Executor<DB: Database<Error: Into<ProviderError> + Display>>: for<'a> Executor<
DB,
Input<'a> = BlockExecutionInput<
'a,
BlockWithSenders<<Self::Primitives as NodePrimitives>::Block>,
>,
Input<'a> = &'a BlockWithSenders<<Self::Primitives as NodePrimitives>::Block>,
Output = BlockExecutionOutput<<Self::Primitives as NodePrimitives>::Receipt>,
Error = BlockExecutionError,
>;
@@ -162,10 +159,7 @@ pub trait BlockExecutorProvider: Send + Sync + Clone + Unpin + 'static {
/// An executor that can execute a batch of blocks given a database.
type BatchExecutor<DB: Database<Error: Into<ProviderError> + Display>>: for<'a> BatchExecutor<
DB,
Input<'a> = BlockExecutionInput<
'a,
BlockWithSenders<<Self::Primitives as NodePrimitives>::Block>,
>,
Input<'a> = &'a BlockWithSenders<<Self::Primitives as NodePrimitives>::Block>,
Output = ExecutionOutcome<<Self::Primitives as NodePrimitives>::Receipt>,
Error = BlockExecutionError,
>;
@@ -213,21 +207,18 @@ pub trait BlockExecutionStrategy {
fn apply_pre_execution_changes(
&mut self,
block: &BlockWithSenders<<Self::Primitives as NodePrimitives>::Block>,
total_difficulty: U256,
) -> Result<(), Self::Error>;
/// Executes all transactions in the block.
fn execute_transactions(
&mut self,
block: &BlockWithSenders<<Self::Primitives as NodePrimitives>::Block>,
total_difficulty: U256,
) -> Result<ExecuteOutput<<Self::Primitives as NodePrimitives>::Receipt>, Self::Error>;
/// Applies any necessary changes after executing the block's transactions.
fn apply_post_execution_changes(
&mut self,
block: &BlockWithSenders<<Self::Primitives as NodePrimitives>::Block>,
total_difficulty: U256,
receipts: &[<Self::Primitives as NodePrimitives>::Receipt],
) -> Result<Requests, Self::Error>;
@@ -347,8 +338,7 @@ where
S: BlockExecutionStrategy<DB = DB>,
DB: Database<Error: Into<ProviderError> + Display>,
{
type Input<'a> =
BlockExecutionInput<'a, BlockWithSenders<<S::Primitives as NodePrimitives>::Block>>;
type Input<'a> = &'a BlockWithSenders<<S::Primitives as NodePrimitives>::Block>;
type Output = BlockExecutionOutput<<S::Primitives as NodePrimitives>::Receipt>;
type Error = S::Error;
@@ -356,14 +346,10 @@ where
self.strategy.init(env_overrides);
}
fn execute(mut self, input: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
let BlockExecutionInput { block, total_difficulty } = input;
self.strategy.apply_pre_execution_changes(block, total_difficulty)?;
let ExecuteOutput { receipts, gas_used } =
self.strategy.execute_transactions(block, total_difficulty)?;
let requests =
self.strategy.apply_post_execution_changes(block, total_difficulty, &receipts)?;
fn execute(mut self, block: Self::Input<'_>) -> Result<Self::Output, Self::Error> {
self.strategy.apply_pre_execution_changes(block)?;
let ExecuteOutput { receipts, gas_used } = self.strategy.execute_transactions(block)?;
let requests = self.strategy.apply_post_execution_changes(block, &receipts)?;
let state = self.strategy.finish();
Ok(BlockExecutionOutput { state, receipts, requests, gas_used })
@@ -371,19 +357,15 @@ where
fn execute_with_state_closure<F>(
mut self,
input: Self::Input<'_>,
block: Self::Input<'_>,
mut state: F,
) -> Result<Self::Output, Self::Error>
where
F: FnMut(&State<DB>),
{
let BlockExecutionInput { block, total_difficulty } = input;
self.strategy.apply_pre_execution_changes(block, total_difficulty)?;
let ExecuteOutput { receipts, gas_used } =
self.strategy.execute_transactions(block, total_difficulty)?;
let requests =
self.strategy.apply_post_execution_changes(block, total_difficulty, &receipts)?;
self.strategy.apply_pre_execution_changes(block)?;
let ExecuteOutput { receipts, gas_used } = self.strategy.execute_transactions(block)?;
let requests = self.strategy.apply_post_execution_changes(block, &receipts)?;
state(self.strategy.state_ref());
@@ -394,21 +376,17 @@ where
fn execute_with_state_hook<H>(
mut self,
input: Self::Input<'_>,
block: Self::Input<'_>,
state_hook: H,
) -> Result<Self::Output, Self::Error>
where
H: OnStateHook + 'static,
{
let BlockExecutionInput { block, total_difficulty } = input;
self.strategy.with_state_hook(Some(Box::new(state_hook)));
self.strategy.apply_pre_execution_changes(block, total_difficulty)?;
let ExecuteOutput { receipts, gas_used } =
self.strategy.execute_transactions(block, total_difficulty)?;
let requests =
self.strategy.apply_post_execution_changes(block, total_difficulty, &receipts)?;
self.strategy.apply_pre_execution_changes(block)?;
let ExecuteOutput { receipts, gas_used } = self.strategy.execute_transactions(block)?;
let requests = self.strategy.apply_post_execution_changes(block, &receipts)?;
let state = self.strategy.finish();
@@ -447,23 +425,18 @@ where
S: BlockExecutionStrategy<DB = DB, Error = BlockExecutionError>,
DB: Database<Error: Into<ProviderError> + Display>,
{
type Input<'a> =
BlockExecutionInput<'a, BlockWithSenders<<S::Primitives as NodePrimitives>::Block>>;
type Input<'a> = &'a BlockWithSenders<<S::Primitives as NodePrimitives>::Block>;
type Output = ExecutionOutcome<<S::Primitives as NodePrimitives>::Receipt>;
type Error = BlockExecutionError;
fn execute_and_verify_one(&mut self, input: Self::Input<'_>) -> Result<(), Self::Error> {
let BlockExecutionInput { block, total_difficulty } = input;
fn execute_and_verify_one(&mut self, block: Self::Input<'_>) -> Result<(), Self::Error> {
if self.batch_record.first_block().is_none() {
self.batch_record.set_first_block(block.header().number());
}
self.strategy.apply_pre_execution_changes(block, total_difficulty)?;
let ExecuteOutput { receipts, .. } =
self.strategy.execute_transactions(block, total_difficulty)?;
let requests =
self.strategy.apply_post_execution_changes(block, total_difficulty, &receipts)?;
self.strategy.apply_pre_execution_changes(block)?;
let ExecuteOutput { receipts, .. } = self.strategy.execute_transactions(block)?;
let requests = self.strategy.apply_post_execution_changes(block, &receipts)?;
self.strategy.validate_block_post_execution(block, &receipts, &requests)?;
@@ -575,7 +548,7 @@ mod tests {
struct TestExecutor<DB>(PhantomData<DB>);
impl<DB> Executor<DB> for TestExecutor<DB> {
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
type Input<'a> = &'a BlockWithSenders;
type Output = BlockExecutionOutput<Receipt>;
type Error = BlockExecutionError;
@@ -607,7 +580,7 @@ mod tests {
}
impl<DB> BatchExecutor<DB> for TestExecutor<DB> {
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
type Input<'a> = &'a BlockWithSenders;
type Output = ExecutionOutcome;
type Error = BlockExecutionError;
@@ -689,7 +662,6 @@ mod tests {
fn apply_pre_execution_changes(
&mut self,
_block: &BlockWithSenders,
_total_difficulty: U256,
) -> Result<(), Self::Error> {
Ok(())
}
@@ -697,7 +669,6 @@ mod tests {
fn execute_transactions(
&mut self,
_block: &BlockWithSenders,
_total_difficulty: U256,
) -> Result<ExecuteOutput<Receipt>, Self::Error> {
Ok(self.execute_transactions_result.clone())
}
@@ -705,7 +676,6 @@ mod tests {
fn apply_post_execution_changes(
&mut self,
_block: &BlockWithSenders,
_total_difficulty: U256,
_receipts: &[Receipt],
) -> Result<Requests, Self::Error> {
Ok(self.apply_post_execution_changes_result.clone())
@@ -743,7 +713,7 @@ mod tests {
let provider = TestExecutorProvider;
let db = CacheDB::<EmptyDBTyped<ProviderError>>::default();
let executor = provider.executor(db);
let _ = executor.execute(BlockExecutionInput::new(&Default::default(), U256::ZERO));
let _ = executor.execute(&Default::default());
}
#[test]
@@ -766,7 +736,7 @@ mod tests {
let provider = BasicBlockExecutorProvider::new(strategy_factory);
let db = CacheDB::<EmptyDBTyped<ProviderError>>::default();
let executor = provider.executor(db);
let result = executor.execute(BlockExecutionInput::new(&Default::default(), U256::ZERO));
let result = executor.execute(&Default::default());
assert!(result.is_ok());
let block_execution_output = result.unwrap();
@@ -792,11 +762,10 @@ mod tests {
// if we want to apply tx env overrides the executor must be mut.
let mut executor = provider.executor(db);
// execute consumes the executor, so we can only call it once.
// let result = executor.execute(BlockExecutionInput::new(&Default::default(), U256::ZERO));
executor.init(Box::new(|tx_env: &mut TxEnv| {
tx_env.nonce.take();
}));
let result = executor.execute(BlockExecutionInput::new(&Default::default(), U256::ZERO));
let result = executor.execute(&Default::default());
assert!(result.is_ok());
}

View File

@@ -145,9 +145,9 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static {
);
/// Returns a [`CfgEnvWithHandlerCfg`] for the given header.
fn cfg_env(&self, header: &Self::Header, total_difficulty: U256) -> CfgEnvWithHandlerCfg {
fn cfg_env(&self, header: &Self::Header) -> CfgEnvWithHandlerCfg {
let mut cfg = CfgEnvWithHandlerCfg::new(Default::default(), Default::default());
self.fill_cfg_env(&mut cfg, header, total_difficulty);
self.fill_cfg_env(&mut cfg, header);
cfg
}
@@ -155,12 +155,7 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static {
///
/// This __must__ set the corresponding spec id in the handler cfg, based on timestamp or total
/// difficulty
fn fill_cfg_env(
&self,
cfg_env: &mut CfgEnvWithHandlerCfg,
header: &Self::Header,
total_difficulty: U256,
);
fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Self::Header);
/// Fill [`BlockEnv`] field according to the chain spec and given header
fn fill_block_env(&self, block_env: &mut BlockEnv, header: &Self::Header, after_merge: bool) {
@@ -184,10 +179,10 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static {
}
/// Creates a new [`EvmEnv`] for the given header.
fn cfg_and_block_env(&self, header: &Self::Header, total_difficulty: U256) -> EvmEnv {
fn cfg_and_block_env(&self, header: &Self::Header) -> EvmEnv {
let mut cfg = CfgEnvWithHandlerCfg::new(Default::default(), Default::default());
let mut block_env = BlockEnv::default();
self.fill_cfg_and_block_env(&mut cfg, &mut block_env, header, total_difficulty);
self.fill_cfg_and_block_env(&mut cfg, &mut block_env, header);
EvmEnv::new(cfg, block_env)
}
@@ -200,9 +195,8 @@ pub trait ConfigureEvmEnv: Send + Sync + Unpin + Clone + 'static {
cfg: &mut CfgEnvWithHandlerCfg,
block_env: &mut BlockEnv,
header: &Self::Header,
total_difficulty: U256,
) {
self.fill_cfg_env(cfg, header, total_difficulty);
self.fill_cfg_env(cfg, header);
let after_merge = cfg.handler_cfg.spec_id >= SpecId::MERGE;
self.fill_block_env(block_env, header, after_merge);
}

View File

@@ -5,7 +5,7 @@
use crate::{execute::Executor, system_calls::OnStateHook};
use alloy_consensus::BlockHeader;
use metrics::{Counter, Gauge, Histogram};
use reth_execution_types::{BlockExecutionInput, BlockExecutionOutput};
use reth_execution_types::BlockExecutionOutput;
use reth_metrics::Metrics;
use reth_primitives::BlockWithSenders;
use revm_primitives::EvmState;
@@ -97,13 +97,13 @@ impl ExecutorMetrics {
pub fn execute_metered<'a, E, DB, O, Error, B>(
&self,
executor: E,
input: BlockExecutionInput<'a, BlockWithSenders<B>>,
input: &'a BlockWithSenders<B>,
state_hook: Box<dyn OnStateHook>,
) -> Result<BlockExecutionOutput<O>, Error>
where
E: Executor<
DB,
Input<'a> = BlockExecutionInput<'a, BlockWithSenders<B>>,
Input<'a> = &'a BlockWithSenders<B>,
Output = BlockExecutionOutput<O>,
Error = Error,
>,
@@ -114,11 +114,8 @@ impl ExecutorMetrics {
// be accessible.
let wrapper = MeteredStateHook { metrics: self.clone(), inner_hook: state_hook };
// Store reference to block for metered
let block = input.block;
// Use metered to execute and track timing/gas metrics
let output = self.metered(block, || executor.execute_with_state_hook(input, wrapper))?;
let output = self.metered(input, || executor.execute_with_state_hook(input, wrapper))?;
// Update the metrics for the number of accounts, storage slots and bytecodes updated
let accounts = output.state.state.len();
@@ -134,16 +131,12 @@ impl ExecutorMetrics {
}
/// Execute the given block and update metrics for the execution.
pub fn metered_one<F, R, B>(
&self,
input: BlockExecutionInput<'_, BlockWithSenders<B>>,
f: F,
) -> R
pub fn metered_one<F, R, B>(&self, input: &BlockWithSenders<B>, f: F) -> R
where
F: FnOnce(BlockExecutionInput<'_, BlockWithSenders<B>>) -> R,
F: FnOnce(&BlockWithSenders<B>) -> R,
B: reth_primitives_traits::Block,
{
self.metered(input.block, || f(input))
self.metered(input, || f(input))
}
}
@@ -165,7 +158,7 @@ mod tests {
impl Executor<()> for MockExecutor {
type Input<'a>
= BlockExecutionInput<'a, BlockWithSenders>
= &'a BlockWithSenders
where
Self: 'a;
type Output = BlockExecutionOutput<()>;
@@ -236,11 +229,7 @@ mod tests {
fn test_executor_metrics_hook_metrics_recorded() {
let snapshotter = setup_test_recorder();
let metrics = ExecutorMetrics::default();
let input = BlockExecutionInput {
block: &BlockWithSenders::default(),
total_difficulty: Default::default(),
};
let input = BlockWithSenders::default();
let (tx, _rx) = mpsc::channel();
let expected_output = 42;
@@ -266,7 +255,7 @@ mod tests {
state
};
let executor = MockExecutor { state };
let _result = metrics.execute_metered(executor, input, state_hook).unwrap();
let _result = metrics.execute_metered(executor, &input, state_hook).unwrap();
let snapshot = snapshotter.snapshot().into_vec();
@@ -289,11 +278,7 @@ mod tests {
#[test]
fn test_executor_metrics_hook_called() {
let metrics = ExecutorMetrics::default();
let input = BlockExecutionInput {
block: &BlockWithSenders::default(),
total_difficulty: Default::default(),
};
let input = BlockWithSenders::default();
let (tx, rx) = mpsc::channel();
let expected_output = 42;
@@ -302,7 +287,7 @@ mod tests {
let state = EvmState::default();
let executor = MockExecutor { state };
let _result = metrics.execute_metered(executor, input, state_hook).unwrap();
let _result = metrics.execute_metered(executor, &input, state_hook).unwrap();
let actual_output = rx.try_recv().unwrap();
assert_eq!(actual_output, expected_output);

View File

@@ -3,7 +3,7 @@
use alloy_primitives::BlockNumber;
use core::fmt::Display;
use reth_execution_errors::BlockExecutionError;
use reth_execution_types::{BlockExecutionInput, BlockExecutionOutput, ExecutionOutcome};
use reth_execution_types::{BlockExecutionOutput, ExecutionOutcome};
use reth_primitives::{BlockWithSenders, NodePrimitives};
use reth_prune_types::PruneModes;
use reth_storage_errors::provider::ProviderError;
@@ -45,7 +45,7 @@ impl<P: NodePrimitives> BlockExecutorProvider for NoopBlockExecutorProvider<P> {
}
impl<DB, P: NodePrimitives> Executor<DB> for NoopBlockExecutorProvider<P> {
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders<P::Block>>;
type Input<'a> = &'a BlockWithSenders<P::Block>;
type Output = BlockExecutionOutput<P::Receipt>;
type Error = BlockExecutionError;
@@ -77,7 +77,7 @@ impl<DB, P: NodePrimitives> Executor<DB> for NoopBlockExecutorProvider<P> {
}
impl<DB, P: NodePrimitives> BatchExecutor<DB> for NoopBlockExecutorProvider<P> {
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders<P::Block>>;
type Input<'a> = &'a BlockWithSenders<P::Block>;
type Output = ExecutionOutcome<P::Receipt>;
type Error = BlockExecutionError;

View File

@@ -2,7 +2,7 @@
use alloy_consensus::BlockHeader;
use alloy_eips::eip4895::Withdrawal;
use alloy_primitives::{map::HashMap, Address, U256};
use alloy_primitives::{map::HashMap, Address};
use reth_chainspec::EthereumHardforks;
use reth_consensus_common::calc;
use reth_primitives_traits::BlockBody;
@@ -15,7 +15,6 @@ use reth_primitives_traits::BlockBody;
pub fn post_block_balance_increments<ChainSpec, Block>(
chain_spec: &ChainSpec,
block: &Block,
total_difficulty: U256,
) -> HashMap<Address, u128>
where
ChainSpec: EthereumHardforks,
@@ -24,12 +23,7 @@ where
let mut balance_increments = HashMap::default();
// Add block rewards if they are enabled.
if let Some(base_block_reward) = calc::base_block_reward(
chain_spec,
block.header().number(),
block.header().difficulty(),
total_difficulty,
) {
if let Some(base_block_reward) = calc::base_block_reward(chain_spec, block.header().number()) {
// Ommer rewards
if let Some(ommers) = block.body().ommers() {
for ommer in ommers {

View File

@@ -3,15 +3,15 @@
use crate::{
env::EvmEnv,
execute::{
BasicBatchExecutor, BasicBlockExecutor, BatchExecutor, BlockExecutionInput,
BlockExecutionOutput, BlockExecutionStrategy, BlockExecutorProvider, Executor,
BasicBatchExecutor, BasicBlockExecutor, BatchExecutor, BlockExecutionOutput,
BlockExecutionStrategy, BlockExecutorProvider, Executor,
},
provider::EvmEnvProvider,
system_calls::OnStateHook,
ConfigureEvmEnv,
};
use alloy_eips::eip7685::Requests;
use alloy_primitives::{BlockNumber, U256};
use alloy_primitives::BlockNumber;
use parking_lot::Mutex;
use reth_execution_errors::BlockExecutionError;
use reth_execution_types::ExecutionOutcome;
@@ -33,7 +33,7 @@ impl<C: Send + Sync, N: NodePrimitives> EvmEnvProvider<N::BlockHeader>
where
EvmConfig: ConfigureEvmEnv<Header = N::BlockHeader>,
{
Ok(evm_config.cfg_and_block_env(header, U256::MAX))
Ok(evm_config.cfg_and_block_env(header))
}
}
@@ -73,7 +73,7 @@ impl BlockExecutorProvider for MockExecutorProvider {
}
impl<DB> Executor<DB> for MockExecutorProvider {
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
type Input<'a> = &'a BlockWithSenders;
type Output = BlockExecutionOutput<Receipt>;
type Error = BlockExecutionError;
@@ -115,7 +115,7 @@ impl<DB> Executor<DB> for MockExecutorProvider {
}
impl<DB> BatchExecutor<DB> for MockExecutorProvider {
type Input<'a> = BlockExecutionInput<'a, BlockWithSenders>;
type Input<'a> = &'a BlockWithSenders;
type Output = ExecutionOutcome;
type Error = BlockExecutionError;

View File

@@ -90,11 +90,6 @@ where
// Fetch the block
let fetch_block_start = Instant::now();
let td = self
.provider
.header_td_by_number(block_number)?
.ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))?;
// we need the block's transactions along with their hashes
let block = self
.provider
@@ -116,7 +111,7 @@ where
let (unsealed_header, hash) = block.header.split();
let block = P::Block::new(unsealed_header, block.body).with_senders_unchecked(senders);
executor.execute_and_verify_one((&block, td).into())?;
executor.execute_and_verify_one(&block)?;
execution_duration += execute_start.elapsed();
// TODO(alexey): report gas metrics using `block.header.gas_used`
@@ -199,11 +194,6 @@ where
BlockWithSenders<P::Block>,
BlockExecutionOutput<<E::Primitives as NodePrimitives>::Receipt>,
)> {
let td = self
.provider
.header_td_by_number(block_number)?
.ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))?;
// Fetch the block with senders for execution.
let block_with_senders = self
.provider
@@ -217,7 +207,7 @@ where
trace!(target: "exex::backfill", number = block_number, txs = block_with_senders.block.body().transactions().len(), "Executing block");
let block_execution_output = executor.execute((&block_with_senders, td).into())?;
let block_execution_output = executor.execute(&block_with_senders)?;
Ok((block_with_senders, block_execution_output))
}

View File

@@ -5,9 +5,7 @@ use alloy_genesis::{Genesis, GenesisAccount};
use alloy_primitives::{b256, Address, TxKind, U256};
use eyre::OptionExt;
use reth_chainspec::{ChainSpec, ChainSpecBuilder, EthereumHardfork, MAINNET, MIN_TRANSACTION_GAS};
use reth_evm::execute::{
BatchExecutor, BlockExecutionInput, BlockExecutionOutput, BlockExecutorProvider, Executor,
};
use reth_evm::execute::{BatchExecutor, BlockExecutionOutput, BlockExecutorProvider, Executor};
use reth_evm_ethereum::execute::EthExecutorProvider;
use reth_node_api::FullNodePrimitives;
use reth_primitives::{
@@ -71,7 +69,7 @@ where
// Execute the block to produce a block execution output
let mut block_execution_output = EthExecutorProvider::ethereum(chain_spec)
.executor(StateProviderDatabase::new(LatestStateProviderRef::new(&provider)))
.execute(BlockExecutionInput { block, total_difficulty: U256::ZERO })?;
.execute(block)?;
block_execution_output.state.reverts.sort();
// Convert the block execution output to an execution outcome for committing to the database
@@ -206,10 +204,7 @@ where
let executor = EthExecutorProvider::ethereum(chain_spec)
.batch_executor(StateProviderDatabase::new(LatestStateProviderRef::new(&provider)));
let mut execution_outcome = executor.execute_and_verify_batch(vec![
(&block1, U256::ZERO).into(),
(&block2, U256::ZERO).into(),
])?;
let mut execution_outcome = executor.execute_and_verify_batch(vec![&block1, &block2])?;
execution_outcome.state_mut().reverts.sort();
let block1 = block1.seal_slow();

View File

@@ -355,21 +355,15 @@ impl From<Genesis> for OpChainSpec {
.filter_map(|(hardfork, opt)| opt.map(|block| (hardfork, ForkCondition::Block(block))))
.collect::<Vec<_>>();
// Paris
let paris_block_and_final_difficulty =
if let Some(ttd) = genesis.config.terminal_total_difficulty {
block_hardforks.push((
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD {
total_difficulty: ttd,
fork_block: genesis.config.merge_netsplit_block,
},
));
genesis.config.merge_netsplit_block.map(|block| (block, ttd))
} else {
None
};
// We set the paris hardfork for OP networks to zero
block_hardforks.push((
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD {
activation_block_number: 0,
total_difficulty: U256::ZERO,
fork_block: genesis.config.merge_netsplit_block,
},
));
// Time-based hardforks
let time_hardfork_opts = [
@@ -413,7 +407,9 @@ impl From<Genesis> for OpChainSpec {
chain: genesis.config.chain_id.into(),
genesis,
hardforks: ChainHardforks::new(ordered_hardforks),
paris_block_and_final_difficulty,
// We assume no OP network merges, and set the paris block and total difficulty to
// zero
paris_block_and_final_difficulty: Some((0, U256::ZERO)),
base_fee_params: optimism_genesis_info.base_fee_params,
..Default::default()
},
@@ -1006,10 +1002,10 @@ mod tests {
// OpHardfork::Isthmus.boxed(),
];
assert!(expected_hardforks
.iter()
.zip(hardforks.iter())
.all(|(expected, actual)| &**expected == *actual));
for (expected, actual) in expected_hardforks.iter().zip(hardforks.iter()) {
println!("got {expected:?}, {actual:?}");
assert_eq!(&**expected, &**actual);
}
assert_eq!(expected_hardforks.len(), hardforks.len());
}

View File

@@ -25,7 +25,7 @@ use reth_optimism_forks::OpHardfork;
use reth_optimism_primitives::OpPrimitives;
use reth_primitives::{BlockWithSenders, Receipt, TransactionSigned, TxType};
use reth_revm::{Database, State};
use revm_primitives::{db::DatabaseCommit, EnvWithHandlerCfg, ResultAndState, U256};
use revm_primitives::{db::DatabaseCommit, EnvWithHandlerCfg, ResultAndState};
use tracing::trace;
/// Factory for [`OpExecutionStrategy`].
@@ -111,8 +111,8 @@ where
/// Configures a new evm configuration and block environment for the given block.
///
/// Caution: this does not initialize the tx environment.
fn evm_env_for_block(&self, header: &Header, total_difficulty: U256) -> EnvWithHandlerCfg {
let evm_env = self.evm_config.cfg_and_block_env(header, total_difficulty);
fn evm_env_for_block(&self, header: &Header) -> EnvWithHandlerCfg {
let evm_env = self.evm_config.cfg_and_block_env(header);
let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env;
EnvWithHandlerCfg::new_with_cfg_env(cfg_env_with_handler_cfg, block_env, Default::default())
}
@@ -131,17 +131,13 @@ where
self.tx_env_overrides = Some(tx_env_overrides);
}
fn apply_pre_execution_changes(
&mut self,
block: &BlockWithSenders,
total_difficulty: U256,
) -> Result<(), Self::Error> {
fn apply_pre_execution_changes(&mut self, block: &BlockWithSenders) -> Result<(), Self::Error> {
// Set state clear flag if the block is after the Spurious Dragon hardfork.
let state_clear_flag =
(*self.chain_spec).is_spurious_dragon_active_at_block(block.header.number);
self.state.set_state_clear_flag(state_clear_flag);
let env = self.evm_env_for_block(&block.header, total_difficulty);
let env = self.evm_env_for_block(&block.header);
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
self.system_caller.apply_beacon_root_contract_call(
@@ -164,9 +160,8 @@ where
fn execute_transactions(
&mut self,
block: &BlockWithSenders,
total_difficulty: U256,
) -> Result<ExecuteOutput<Receipt>, Self::Error> {
let env = self.evm_env_for_block(&block.header, total_difficulty);
let env = self.evm_env_for_block(&block.header);
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
let is_regolith =
@@ -260,11 +255,10 @@ where
fn apply_post_execution_changes(
&mut self,
block: &BlockWithSenders,
total_difficulty: U256,
_receipts: &[Receipt],
) -> Result<Requests, Self::Error> {
let balance_increments =
post_block_balance_increments(&self.chain_spec.clone(), &block.block, total_difficulty);
post_block_balance_increments(&self.chain_spec.clone(), &block.block);
// increment balances
self.state
.increment_balances(balance_increments.clone())
@@ -317,7 +311,7 @@ mod tests {
use crate::OpChainSpec;
use alloy_consensus::TxEip1559;
use alloy_primitives::{
b256, Address, PrimitiveSignature as Signature, StorageKey, StorageValue,
b256, Address, PrimitiveSignature as Signature, StorageKey, StorageValue, U256,
};
use op_alloy_consensus::TxDeposit;
use reth_chainspec::MIN_TRANSACTION_GAS;
@@ -417,22 +411,13 @@ mod tests {
// Attempt to execute a block with one deposit and one non-deposit transaction
executor
.execute_and_verify_one(
(
&BlockWithSenders {
block: Block {
header,
body: BlockBody {
transactions: vec![tx, tx_deposit],
..Default::default()
},
},
senders: vec![addr, addr],
},
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders {
block: Block {
header,
body: BlockBody { transactions: vec![tx, tx_deposit], ..Default::default() },
},
senders: vec![addr, addr],
})
.unwrap();
let receipts = executor.receipts();
@@ -501,22 +486,13 @@ mod tests {
// attempt to execute an empty block with parent beacon block root, this should not fail
executor
.execute_and_verify_one(
(
&BlockWithSenders {
block: Block {
header,
body: BlockBody {
transactions: vec![tx, tx_deposit],
..Default::default()
},
},
senders: vec![addr, addr],
},
U256::ZERO,
)
.into(),
)
.execute_and_verify_one(&BlockWithSenders {
block: Block {
header,
body: BlockBody { transactions: vec![tx, tx_deposit], ..Default::default() },
},
senders: vec![addr, addr],
})
.expect("Executing a block while canyon is active should not fail");
let receipts = executor.receipts();

View File

@@ -110,19 +110,16 @@ impl ConfigureEvmEnv for OpEvmConfig {
env.block.basefee = U256::ZERO;
}
fn fill_cfg_env(
&self,
cfg_env: &mut CfgEnvWithHandlerCfg,
header: &Self::Header,
total_difficulty: U256,
) {
fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Self::Header) {
let spec_id = revm_spec(
self.chain_spec(),
&Head {
number: header.number,
timestamp: header.timestamp,
difficulty: header.difficulty,
total_difficulty,
// NOTE: this does not matter within revm_spec as it uses paris hardfork block
// activation
total_difficulty: U256::MIN,
hash: Default::default(),
},
);
@@ -246,14 +243,11 @@ mod tests {
.shanghai_activated()
.build();
// Define the total difficulty as zero (default)
let total_difficulty = U256::ZERO;
// Use the `OpEvmConfig` to create the `cfg_env` and `block_env` based on the ChainSpec,
// Header, and total difficulty
let EvmEnv { cfg_env_with_handler_cfg, .. } =
OpEvmConfig::new(Arc::new(OpChainSpec { inner: chain_spec.clone() }))
.cfg_and_block_env(&header, total_difficulty);
.cfg_and_block_env(&header);
// Assert that the chain ID in the `cfg_env` is correctly set to the chain ID of the
// ChainSpec

View File

@@ -23,7 +23,11 @@ pub static DEV_HARDFORKS: LazyLock<ChainHardforks> = LazyLock::new(|| {
(EthereumHardfork::London.boxed(), ForkCondition::Block(0)),
(
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD { fork_block: None, total_difficulty: U256::ZERO },
ForkCondition::TTD {
activation_block_number: 0,
fork_block: None,
total_difficulty: U256::ZERO,
},
),
(crate::OpHardfork::Bedrock.boxed(), ForkCondition::Block(0)),
(crate::OpHardfork::Regolith.boxed(), ForkCondition::Timestamp(0)),

View File

@@ -220,7 +220,11 @@ impl OpHardfork {
(EthereumHardfork::GrayGlacier.boxed(), ForkCondition::Block(105235063)),
(
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD { fork_block: Some(105235063), total_difficulty: U256::ZERO },
ForkCondition::TTD {
activation_block_number: 105235063,
fork_block: Some(105235063),
total_difficulty: U256::ZERO,
},
),
(Self::Bedrock.boxed(), ForkCondition::Block(105235063)),
(Self::Regolith.boxed(), ForkCondition::Timestamp(0)),
@@ -252,7 +256,11 @@ impl OpHardfork {
(EthereumHardfork::GrayGlacier.boxed(), ForkCondition::Block(0)),
(
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO },
ForkCondition::TTD {
activation_block_number: 0,
fork_block: Some(0),
total_difficulty: U256::ZERO,
},
),
(Self::Bedrock.boxed(), ForkCondition::Block(0)),
(Self::Regolith.boxed(), ForkCondition::Timestamp(0)),
@@ -284,7 +292,11 @@ impl OpHardfork {
(EthereumHardfork::GrayGlacier.boxed(), ForkCondition::Block(0)),
(
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO },
ForkCondition::TTD {
activation_block_number: 0,
fork_block: Some(0),
total_difficulty: U256::ZERO,
},
),
(Self::Bedrock.boxed(), ForkCondition::Block(0)),
(Self::Regolith.boxed(), ForkCondition::Timestamp(0)),
@@ -316,7 +328,11 @@ impl OpHardfork {
(EthereumHardfork::GrayGlacier.boxed(), ForkCondition::Block(0)),
(
EthereumHardfork::Paris.boxed(),
ForkCondition::TTD { fork_block: Some(0), total_difficulty: U256::ZERO },
ForkCondition::TTD {
activation_block_number: 0,
fork_block: Some(0),
total_difficulty: U256::ZERO,
},
),
(Self::Bedrock.boxed(), ForkCondition::Block(0)),
(Self::Regolith.boxed(), ForkCondition::Timestamp(0)),

View File

@@ -641,12 +641,9 @@ where
let mut witness_record = ExecutionWitnessRecord::default();
let _ = block_executor
.execute_with_state_closure(
(&(*block).clone().unseal(), block.difficulty()).into(),
|statedb: &State<_>| {
witness_record.record_executed_state(statedb);
},
)
.execute_with_state_closure(&(*block).clone().unseal(), |statedb: &State<_>| {
witness_record.record_executed_state(statedb);
})
.map_err(|err| EthApiError::Internal(err.into()))?;
let ExecutionWitnessRecord { hashed_state, codes, keys } = witness_record;

View File

@@ -14,13 +14,11 @@ use alloy_rpc_types_trace::{
};
use async_trait::async_trait;
use jsonrpsee::core::RpcResult;
use reth_chainspec::EthereumHardforks;
use reth_consensus_common::calc::{
base_block_reward, base_block_reward_pre_merge, block_reward, ommer_reward,
};
use reth_chainspec::{EthChainSpec, EthereumHardfork, MAINNET, SEPOLIA};
use reth_consensus_common::calc::{base_block_reward_pre_merge, block_reward, ommer_reward};
use reth_evm::{env::EvmEnv, ConfigureEvmEnv};
use reth_primitives_traits::{BlockBody, BlockHeader};
use reth_provider::{BlockNumReader, BlockReader, ChainSpecProvider, HeaderProvider};
use reth_provider::{BlockNumReader, BlockReader, ChainSpecProvider};
use reth_revm::database::StateProviderDatabase;
use reth_rpc_api::TraceApiServer;
use reth_rpc_eth_api::{helpers::TraceExt, FromEthApiError, RpcNodeCore};
@@ -313,9 +311,7 @@ where
// add reward traces for all blocks
for block in &blocks {
if let Some(base_block_reward) =
self.calculate_base_block_reward(block.header.header())?
{
if let Some(base_block_reward) = self.calculate_base_block_reward(block.header())? {
all_traces.extend(
self.extract_reward_traces(
block.header.header(),
@@ -509,30 +505,19 @@ where
header: &H,
) -> Result<Option<u128>, Eth::Error> {
let chain_spec = self.provider().chain_spec();
let is_paris_activated = chain_spec.is_paris_active_at_block(header.number());
let is_paris_activated = if chain_spec.chain() == MAINNET.chain() {
Some(header.number()) >= EthereumHardfork::Paris.mainnet_activation_block()
} else if chain_spec.chain() == SEPOLIA.chain() {
Some(header.number()) >= EthereumHardfork::Paris.sepolia_activation_block()
} else {
true
};
Ok(match is_paris_activated {
Some(true) => None,
Some(false) => Some(base_block_reward_pre_merge(&chain_spec, header.number())),
None => {
// if Paris hardfork is unknown, we need to fetch the total difficulty at the
// block's height and check if it is pre-merge to calculate the base block reward
if let Some(header_td) = self
.provider()
.header_td_by_number(header.number())
.map_err(Eth::Error::from_eth_err)?
{
base_block_reward(
chain_spec.as_ref(),
header.number(),
header.difficulty(),
header_td,
)
} else {
None
}
}
})
if is_paris_activated {
return Ok(None)
}
Ok(Some(base_block_reward_pre_merge(&chain_spec, header.number())))
}
/// Extracts the reward traces for the given block:

View File

@@ -19,9 +19,7 @@ use reth_errors::{BlockExecutionError, ConsensusError, ProviderError};
use reth_evm::execute::{BlockExecutorProvider, Executor};
use reth_primitives::{GotExpected, NodePrimitives, SealedBlockWithSenders, SealedHeader};
use reth_primitives_traits::{constants::GAS_LIMIT_BOUND_DIVISOR, Block as _, BlockBody};
use reth_provider::{
BlockExecutionInput, BlockExecutionOutput, BlockReaderIdExt, StateProviderFactory,
};
use reth_provider::{BlockExecutionOutput, BlockReaderIdExt, StateProviderFactory};
use reth_revm::{cached::CachedReads, database::StateProviderDatabase};
use reth_rpc_api::BlockSubmissionValidationApiServer;
use reth_rpc_server_types::result::internal_rpc_err;
@@ -152,18 +150,15 @@ where
let block = block.unseal();
let mut accessed_blacklisted = None;
let output = executor.execute_with_state_closure(
BlockExecutionInput::new(&block, U256::MAX),
|state| {
if !self.disallow.is_empty() {
for account in state.cache.accounts.keys() {
if self.disallow.contains(account) {
accessed_blacklisted = Some(*account);
}
let output = executor.execute_with_state_closure(&block, |state| {
if !self.disallow.is_empty() {
for account in state.cache.accounts.keys() {
if self.disallow.contains(account) {
accessed_blacklisted = Some(*account);
}
}
},
)?;
}
})?;
// update the cached reads
self.update_cached_reads(latest_header_hash, request_cache).await;

View File

@@ -337,10 +337,6 @@ where
// Fetch the block
let fetch_block_start = Instant::now();
let td = provider
.header_td_by_number(block_number)?
.ok_or_else(|| ProviderError::HeaderNotFound(block_number.into()))?;
// we need the block's transactions but we don't need the transaction hashes
let block = provider
.block_with_senders(block_number.into(), TransactionVariant::NoHash)?
@@ -356,7 +352,7 @@ where
// Execute the block
let execute_start = Instant::now();
self.metrics.metered_one((&block, td).into(), |input| {
self.metrics.metered_one(&block, |input| {
executor.execute_and_verify_one(input).map_err(|error| {
let header = block.header();
StageError::Block {

View File

@@ -1241,10 +1241,7 @@ impl<N: ProviderNodeTypes> EvmEnvProvider<HeaderTy<N>> for ConsistentProvider<N>
where
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let total_difficulty = self
.header_td_by_number(header.number())?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number().into()))?;
Ok(evm_config.cfg_and_block_env(header, total_difficulty))
Ok(evm_config.cfg_and_block_env(header))
}
}

View File

@@ -1651,10 +1651,7 @@ impl<TX: DbTx + 'static, N: NodeTypesForProvider> EvmEnvProvider<HeaderTy<N>>
where
EvmConfig: ConfigureEvmEnv<Header = HeaderTy<N>>,
{
let total_difficulty = self
.header_td_by_number(header.number())?
.ok_or_else(|| ProviderError::HeaderNotFound(header.number().into()))?;
Ok(evm_config.cfg_and_block_env(header, total_difficulty))
Ok(evm_config.cfg_and_block_env(header))
}
}

View File

@@ -716,7 +716,7 @@ impl EvmEnvProvider for MockEthProvider {
where
EvmConfig: ConfigureEvmEnv<Header = Header>,
{
Ok(evm_config.cfg_and_block_env(header, U256::MAX))
Ok(evm_config.cfg_and_block_env(header))
}
}

View File

@@ -129,12 +129,8 @@ where
/// # Caution
///
/// This does not initialize the tx environment.
fn evm_env_for_block(
&self,
header: &alloy_consensus::Header,
total_difficulty: U256,
) -> EnvWithHandlerCfg {
let evm_env = self.evm_config.cfg_and_block_env(header, total_difficulty);
fn evm_env_for_block(&self, header: &alloy_consensus::Header) -> EnvWithHandlerCfg {
let evm_env = self.evm_config.cfg_and_block_env(header);
let EvmEnv { cfg_env_with_handler_cfg, block_env } = evm_env;
EnvWithHandlerCfg::new_with_cfg_env(cfg_env_with_handler_cfg, block_env, Default::default())
}
@@ -148,11 +144,7 @@ where
type Primitives = EthPrimitives;
type Error = BlockExecutionError;
fn apply_pre_execution_changes(
&mut self,
block: &BlockWithSenders,
_total_difficulty: U256,
) -> Result<(), Self::Error> {
fn apply_pre_execution_changes(&mut self, block: &BlockWithSenders) -> Result<(), Self::Error> {
// Set state clear flag if the block is after the Spurious Dragon hardfork.
let state_clear_flag =
(*self.chain_spec).is_spurious_dragon_active_at_block(block.header.number);
@@ -164,7 +156,6 @@ where
fn execute_transactions(
&mut self,
_block: &BlockWithSenders,
_total_difficulty: U256,
) -> Result<ExecuteOutput<Receipt>, Self::Error> {
Ok(ExecuteOutput { receipts: vec![], gas_used: 0 })
}
@@ -172,10 +163,9 @@ where
fn apply_post_execution_changes(
&mut self,
block: &BlockWithSenders,
total_difficulty: U256,
_receipts: &[Receipt],
) -> Result<Requests, Self::Error> {
let env = self.evm_env_for_block(&block.header, total_difficulty);
let env = self.evm_env_for_block(&block.header);
let mut evm = self.evm_config.evm_with_env(&mut self.state, env);
if let Some(withdrawals) = block.body.withdrawals.as_ref() {

View File

@@ -4,7 +4,7 @@
use alloy_consensus::Header;
use alloy_genesis::Genesis;
use alloy_primitives::{address, Address, Bytes, U256};
use alloy_primitives::{address, Address, Bytes};
use reth::{
builder::{
components::{ExecutorBuilder, PayloadServiceBuilder},
@@ -103,13 +103,8 @@ impl ConfigureEvmEnv for MyEvmConfig {
self.inner.fill_tx_env_system_contract_call(env, caller, contract, data);
}
fn fill_cfg_env(
&self,
cfg_env: &mut CfgEnvWithHandlerCfg,
header: &Self::Header,
total_difficulty: U256,
) {
self.inner.fill_cfg_env(cfg_env, header, total_difficulty);
fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Self::Header) {
self.inner.fill_cfg_env(cfg_env, header);
}
fn next_cfg_and_block_env(

View File

@@ -4,7 +4,7 @@
use alloy_consensus::Header;
use alloy_genesis::Genesis;
use alloy_primitives::{Address, Bytes, U256};
use alloy_primitives::{Address, Bytes};
use parking_lot::RwLock;
use reth::{
api::NextBlockEnvAttributes,
@@ -165,13 +165,8 @@ impl ConfigureEvmEnv for MyEvmConfig {
self.inner.fill_tx_env_system_contract_call(env, caller, contract, data)
}
fn fill_cfg_env(
&self,
cfg_env: &mut CfgEnvWithHandlerCfg,
header: &Self::Header,
total_difficulty: U256,
) {
self.inner.fill_cfg_env(cfg_env, header, total_difficulty)
fn fill_cfg_env(&self, cfg_env: &mut CfgEnvWithHandlerCfg, header: &Self::Header) {
self.inner.fill_cfg_env(cfg_env, header)
}
fn next_cfg_and_block_env(