mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
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:
@ -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()
|
||||
}
|
||||
),
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
Reference in New Issue
Block a user