Skip to content

Commit

Permalink
Extend tests and fixes for Cancun hard fork
Browse files Browse the repository at this point in the history
  • Loading branch information
mrLSD committed Apr 30, 2024
1 parent 1b68719 commit 34a808f
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 48 deletions.
12 changes: 8 additions & 4 deletions evm-tests/jsontests/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,16 +184,20 @@ fn short_test_file_name(name: &str) -> String {
}

const SKIPPED_CASES: &[&str] = &[
// funky test with `bigint 0x00` value in json :) not possible to happen on mainnet and require
// custom json parser. https://github.com/ethereum/tests/issues/971
"stTransactionTest/ValueOverflow",
"stTransactionTest/ValueOverflowParis",
"stTransactionTest/HighGasPrice",
"stTransactionTest/HighGasPriceParis",
"stCreateTest/CreateTransactionHighNonce",
// Long execution
"stTimeConsuming/static_Call50000_sha256",
"stTimeConsuming/CALLBlake2f_MaxRounds",
"vmPerformance/loopMul",
"stTimeConsuming/CALLBlake2f_MaxRounds",
// Skip python-specific tests
"Pyspecs",
// KZG-precompile not supported
"stPreCompiledContracts/precompsEIP2929Cancun",
"stEIP4844-blobtransactions/",
"stEIP3607",
];

fn should_skip(path: &Path) -> bool {
Expand Down
3 changes: 3 additions & 0 deletions evm-tests/jsontests/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ fn test_run(
.map_or_else(U256::zero, |acc| acc.balance);

for (i, state) in states.iter().enumerate() {
// if i != 10 {
// continue;
// }
let transaction = test.0.transaction.select(&state.indexes);
let mut backend = MemoryBackend::new(&vicinity, original_state.clone());

Expand Down
11 changes: 10 additions & 1 deletion evm-tests/jsontests/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,16 @@ pub mod transaction {
return Err(InvalidTxReason::GasLimitReached);
}

let required_funds = tx.gas_limit.0 * tx.gas_price.0 + tx.value.0;
let required_funds = if let Some(x) = tx.gas_limit.0.checked_mul(tx.gas_price.0) {
if let Some(y) = x.checked_add(tx.value.0) {
y
} else {
return Err(InvalidTxReason::OutOfFund);
}
} else {
return Err(InvalidTxReason::OutOfFund);
};

if caller_balance < required_funds {
return Err(InvalidTxReason::OutOfFund);
}
Expand Down
19 changes: 9 additions & 10 deletions evm-tests/jsontests/tests/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ fn short_test_file_name(name: &str) -> String {
}

pub fn run(dir: &str) {
// const SPEC: Option<ForkSpec> = Some(ForkSpec::Cancun);
const SPEC: Option<ForkSpec> = Some(ForkSpec::Shanghai);
const SPEC: Option<ForkSpec> = Some(ForkSpec::Cancun);
//const SPEC: Option<ForkSpec> = Some(ForkSpec::Shanghai);

let _ = env_logger::try_init();

Expand All @@ -26,10 +26,10 @@ pub fn run(dir: &str) {

let mut tests_result = TestExecutionResult::new();
let verbose_output = VerboseOutput {
verbose: true,
very_verbose: true,
verbose_failed: true,
print_state: true,
verbose: false,
very_verbose: false,
verbose_failed: false,
print_state: false,
};
for entry in fs::read_dir(dest).unwrap() {
let entry = entry.unwrap();
Expand All @@ -41,7 +41,6 @@ pub fn run(dir: &str) {

let path = entry.path();
let filename = path.to_str().unwrap();
// println!("RUM for: {}", short_test_file_name(filename));

if should_skip(&path) {
println!("Skipping test case {}", short_test_file_name(filename));
Expand All @@ -58,9 +57,6 @@ pub fn run(dir: &str) {

for (name, test) in test_suite {
let test_res = statetests::test(verbose_output.clone(), &name, test, SPEC);
// println!("Tests count: {}", test_res.total);
// println!("Failed: {}\n", test_res.failed);

tests_result.merge(test_res);
}
}
Expand All @@ -84,9 +80,12 @@ const SKIPPED_CASES: &[&str] = &[
"stTransactionTest/HighGasPrice",
"stTransactionTest/HighGasPriceParis",
"stCreateTest/CreateTransactionHighNonce",
// KZG-precompile not supported
"stPreCompiledContracts/precompsEIP2929Cancun",
];

fn should_skip(path: &Path) -> bool {
println!("{path:?}");
let matches = |case: &str| {
let file_stem = path.file_stem().unwrap();
let dir_path = path.parent().unwrap();
Expand Down
2 changes: 1 addition & 1 deletion gasometer/src/costs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ pub fn call_cost(
+ new_cost(is_call_or_staticcall, new_account, transfers_value, config)
}

pub const fn address_access_cost(is_cold: bool, regular_value: u64, config: &Config) -> u64 {
pub fn address_access_cost(is_cold: bool, regular_value: u64, config: &Config) -> u64 {
if config.increase_state_access_gas {
if is_cold {
config.gas_account_access_cold
Expand Down
12 changes: 11 additions & 1 deletion gasometer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ macro_rules! log_gas {
($self:expr, $($arg:tt)*) => (
log::trace!(target: "evm", "Gasometer {} [Gas used: {}, Gas left: {}]", format_args!($($arg)*),
$self.total_used_gas(), $self.gas());
println!(" Gasometer {} [Gas used: {}, Gas left: {}]", format_args!($($arg)*), $self.total_used_gas(), $self.gas());
// TODOFEE
//println!(" Gasometer {} [Gas used: {}, Gas left: {}]", format_args!($($arg)*), $self.total_used_gas(), $self.gas());
);
}

Expand Down Expand Up @@ -762,6 +763,15 @@ pub fn dynamic_opcode_cost<H: Handler>(
len: 32,
}),

Opcode::MCOPY => Some(MemoryCost {
offset: {
let src = stack.peek_usize(0)?;
let dst = stack.peek_usize(1)?;
max(src, dst)
},
len: stack.peek_usize(2)?,
}),

Opcode::MSTORE8 => Some(MemoryCost {
offset: stack.peek_usize(0)?,
len: 1,
Expand Down
5 changes: 4 additions & 1 deletion runtime/src/eval/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ pub fn eval<H: Handler>(state: &mut Runtime, opcode: Opcode, handler: &mut H) ->
Opcode::LOG3 => system::log(state, 3, handler),
Opcode::LOG4 => system::log(state, 4, handler),
Opcode::SUICIDE => system::selfdestruct(state, handler),
Opcode::CREATE => system::create(state, false, handler),
Opcode::CREATE => {
let res = system::create(state, false, handler);
res
}
Opcode::CREATE2 => system::create(state, true, handler),
Opcode::CALL => system::call(state, CallScheme::Call, handler),
Opcode::CALLCODE => system::call(state, CallScheme::CallCode, handler),
Expand Down
25 changes: 11 additions & 14 deletions src/executor/stack/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ pub struct StackSubstateMetadata<'config> {
is_static: bool,
depth: Option<usize>,
accessed: Option<Accessed>,
created: BTreeSet<H160>,
}

impl<'config> StackSubstateMetadata<'config> {
Expand All @@ -92,6 +93,7 @@ impl<'config> StackSubstateMetadata<'config> {
is_static: false,
depth: None,
accessed,
created: BTreeSet::new(),
}
}

Expand Down Expand Up @@ -130,6 +132,7 @@ impl<'config> StackSubstateMetadata<'config> {
is_static: is_static || self.is_static,
depth: self.depth.map_or(Some(0), |n| Some(n + 1)),
accessed: self.accessed.as_ref().map(|_| Accessed::default()),
created: self.created.clone(),
}
}

Expand Down Expand Up @@ -196,7 +199,7 @@ pub trait StackState<'config>: Backend {

fn is_empty(&self, address: H160) -> bool;
fn deleted(&self, address: H160) -> bool;
fn created(&self, address: H160) -> bool;
fn is_created(&self, address: H160) -> bool;
fn is_cold(&self, address: H160) -> bool;
fn is_storage_cold(&self, address: H160, key: H256) -> bool;

Expand Down Expand Up @@ -638,7 +641,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>

let transaction_cost = gasometer::call_transaction_cost(&data, &access_list);
// TODOFEE
println!("transaction_cost: {transaction_cost:?}");
// println!("transaction_cost: {transaction_cost:?}");
let gasometer = &mut self.state.metadata_mut().gasometer;
match gasometer.record_transaction(transaction_cost) {
Ok(()) => (),
Expand Down Expand Up @@ -868,7 +871,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
}
// It needed for CANCUN hard fork EIP-6780 we should mark account as created
// to handle SELFDESTRUCT in the same transaction
self.set_created(address);
self.state.set_created(address);

if self.config.create_increase_nonce {
if let Err(e) = self.state.inc_nonce(address) {
Expand Down Expand Up @@ -1127,14 +1130,9 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet>
}
}

/// Sed address created.
fn set_created(&mut self, address: H160) {
self.state.set_created(address)
}

/// Check whether an address has already been created.
fn created(&self, address: H160) -> bool {
self.state.created(address)
fn is_created(&self, address: H160) -> bool {
self.state.is_created(address)
}
}

Expand Down Expand Up @@ -1170,7 +1168,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Interprete
}

// TODOFEE
println!("OPCODE: {opcode:?}");
// println!("OPCODE: {opcode:?}");
if let Some(cost) = gasometer::static_opcode_cost(opcode) {
self.state
.metadata_mut()
Expand Down Expand Up @@ -1355,7 +1353,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
/// Mark account as deleted
/// - SELFDESTRUCT - CANCUN hard fork: EIP-6780
fn mark_delete(&mut self, address: H160, target: H160) -> Result<(), ExitError> {
let is_created = self.created(address);
let is_created = self.is_created(address);
// SELFDESTRUCT - CANCUN hard fork: EIP-6780 - selfdestruct only if contract is created in the same tx
if self.config.has_restricted_selfdestruct && !is_created && address == target {
// State is not changed:
Expand All @@ -1380,7 +1378,7 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
self.state.reset_balance(address);
// For CANCUN hard fork SELFDESTRUCT (EIP-6780) state is not changed
// or if SELFDESTRUCT in the same TX - account should selfdestruct
if !self.config.has_restricted_selfdestruct || self.created(address) {
if !self.config.has_restricted_selfdestruct || self.is_created(address) {
self.state.set_deleted(address);
}

Expand All @@ -1401,7 +1399,6 @@ impl<'config, 'precompiles, S: StackState<'config>, P: PrecompileSet> Handler
emit_exit!(reason.clone());
return Capture::Exit((reason, None, Vec::new()));
}

self.create_inner(caller, scheme, value, init_code, target_gas, true)
}

Expand Down
33 changes: 17 additions & 16 deletions src/executor/stack/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,7 @@ impl<'config> MemoryStackSubstate<'config> {
self.storages.append(&mut exited.storages);
self.tstorages.append(&mut exited.tstorages);
self.deletes.append(&mut exited.deletes);
self.creates.append(&mut exited.creates);

Ok(())
}
Expand Down Expand Up @@ -282,18 +283,6 @@ impl<'config> MemoryStackSubstate<'config> {
false
}

pub fn created(&self, address: H160) -> bool {
if self.creates.contains(&address) {
return true;
}

if let Some(parent) = self.parent.as_ref() {
return parent.created(address);
}

false
}

#[allow(clippy::map_entry)]
fn account_mut<B: Backend>(&mut self, address: H160, backend: &B) -> &mut MemoryStackAccount {
if !self.accounts.contains_key(&address) {
Expand Down Expand Up @@ -362,6 +351,18 @@ impl<'config> MemoryStackSubstate<'config> {
self.creates.insert(address);
}

pub fn is_created(&self, address: H160) -> bool {
if self.creates.contains(&address) {
return true;
}

if let Some(parent) = self.parent.as_ref() {
return parent.is_created(address);
}

false
}

pub fn set_code<B: Backend>(&mut self, address: H160, code: Vec<u8>, backend: &B) {
self.account_mut(address, backend).code = Some(code);
}
Expand Down Expand Up @@ -554,10 +555,6 @@ impl<'backend, 'config, B: Backend> StackState<'config> for MemoryStackState<'ba
self.substate.deleted(address)
}

fn created(&self, address: H160) -> bool {
self.substate.created(address)
}

fn is_cold(&self, address: H160) -> bool {
self.substate.is_cold(address)
}
Expand Down Expand Up @@ -590,6 +587,10 @@ impl<'backend, 'config, B: Backend> StackState<'config> for MemoryStackState<'ba
self.substate.set_created(address)
}

fn is_created(&self, address: H160) -> bool {
self.substate.is_created(address)
}

fn set_code(&mut self, address: H160, code: Vec<u8>) {
self.substate.set_code(address, code, self.backend)
}
Expand Down

0 comments on commit 34a808f

Please sign in to comment.