From 49812612c31d827c9b3a08565c50c7b8be00ec3e Mon Sep 17 00:00:00 2001 From: Esteban Dimitroff Hodi Date: Fri, 22 May 2026 15:38:12 -0300 Subject: [PATCH 1/4] fix(l1): make statetest _info optional and add Osaka to runnable forks --- .../ef_tests/state_v2/src/modules/report.rs | 35 +++---- .../ef_tests/state_v2/src/modules/runner.rs | 6 +- .../ef_tests/state_v2/src/modules/types.rs | 96 ++++++++++++++++--- 3 files changed, 103 insertions(+), 34 deletions(-) diff --git a/tooling/ef_tests/state_v2/src/modules/report.rs b/tooling/ef_tests/state_v2/src/modules/report.rs index 9a892e2aec9..1881e83a98a 100644 --- a/tooling/ef_tests/state_v2/src/modules/report.rs +++ b/tooling/ef_tests/state_v2/src/modules/report.rs @@ -75,27 +75,22 @@ pub fn write_failing_test_to_report(test: &Test, failing_test_cases: Vec) -> Result<(), RunnerError> { vec!["eip-7594", "eip-7939", "eip-7918", "eip-7892", "eip-7883"]; for test in tests { - let test_eip = test._info.clone().reference_spec.unwrap_or_default(); + let test_eip = test + ._info + .as_ref() + .and_then(|info| info.reference_spec.clone()) + .unwrap_or_default(); if test.path.to_str().unwrap().contains("osaka") && !fusaka_eips_to_test.iter().any(|eip| test_eip.contains(eip)) diff --git a/tooling/ef_tests/state_v2/src/modules/types.rs b/tooling/ef_tests/state_v2/src/modules/types.rs index 1fa0339e8aa..b9d74cb48a7 100644 --- a/tooling/ef_tests/state_v2/src/modules/types.rs +++ b/tooling/ef_tests/state_v2/src/modules/types.rs @@ -27,7 +27,7 @@ use std::{ path::PathBuf, }; -const DEFAULT_FORKS: [&str; 5] = ["Merge", "Shanghai", "Cancun", "Prague", "Amsterdam"]; +const DEFAULT_FORKS: [&str; 6] = ["Merge", "Shanghai", "Cancun", "Prague", "Osaka", "Amsterdam"]; /// `Tests` structure is the result of parsing a whole `.json` file from the EF tests. This file includes at /// least one general test enviroment and different test cases inside each enviroment. @@ -117,17 +117,17 @@ impl Tests { test_data: &HashMap, test_cases: Vec, ) -> Result { - // Obtain the value of the `info` field in the JSON. - let info_field = test_data - .get("_info") - .ok_or(serde::de::Error::missing_field("_info"))?; - // Parse the field value as `Info`. - let test_info = serde_json::from_value(info_field.clone()).map_err(|err| { - serde::de::Error::custom(format!( - "Failed to deserialize `info` field in test {}. Serde error: {}", - test_name, err - )) - })?; + // The `_info` field is optional — EF fixtures populate it but + // goevmlab-generated fixtures may omit it. + let test_info = match test_data.get("_info") { + Some(info_field) => Some(serde_json::from_value(info_field.clone()).map_err(|err| { + serde::de::Error::custom(format!( + "Failed to deserialize `info` field in test {}. Serde error: {}", + test_name, err + )) + })?), + None => None, + }; // Obtain the value of the `env` field in the JSON. let env_field = test_data .get("env") @@ -226,7 +226,7 @@ impl Tests { pub struct Test { pub name: String, // The name of the test object inside the .json file. pub path: PathBuf, // The path of the .json file the Test can be found at. - pub _info: Info, // General information about the test. + pub _info: Option, // General information about the test (optional — present in EF fixtures, may be absent in goevmlab-generated ones). pub env: Env, // The block enviroment before the test transaction happens. pub pre: HashMap, // The accounts state previous to the test transaction. pub test_cases: Vec, // A vector of specific cases to be tested under these conditions (transactions). @@ -560,3 +560,73 @@ pub struct RawTransaction { #[serde(default, deserialize_with = "deserialize_authorization_lists")] pub authorization_list: Option>, } + +#[cfg(test)] +mod tests { + use super::*; + + /// Minimal fixture body — Tests::deserialize parses every test object as a + /// (test_name -> raw fields) map, so the inner fields just need to be + /// shape-correct enough for the per-field parsers downstream. + fn fixture_json(with_info: bool) -> String { + let info = if with_info { + r#""_info": { "comment": "goevmlab-generated" },"# + } else { + "" + }; + format!( + r#"{{ + "blockhash_divergence": {{ + {info} + "env": {{ + "currentCoinbase": "0xb94f5374fce5edbc8e2a8697c15331677e6ebf0b", + "currentDifficulty": "0x200000", + "currentRandom": "0x0000000000000000000000000000000000000000000000000000000000200000", + "currentGasLimit": "0x26e1f476fe1e22", + "currentNumber": "0x1", + "currentTimestamp": "0x3e8", + "previousHash": "0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", + "currentBaseFee": "0x10" + }}, + "pre": {{}}, + "transaction": {{ + "gasPrice": "0x10", + "nonce": "0x0", + "to": "0x00000000000000000000000000000000000000f1", + "data": ["0x"], + "gasLimit": ["0x5f5e100"], + "value": ["0x0"], + "secretKey": "0x45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", + "sender": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b" + }}, + "post": {{ + "Prague": [ + {{ + "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "logs": "0x0000000000000000000000000000000000000000000000000000000000000000", + "indexes": {{ "data": 0, "gas": 0, "value": 0 }} + }} + ] + }} + }} + }}"# + ) + } + + #[test] + fn fixture_without_info_parses() { + let json = fixture_json(false); + let tests: Tests = serde_json::from_str(&json).expect("must parse without _info"); + assert_eq!(tests.0.len(), 1); + assert!(tests.0[0]._info.is_none(), "_info should be None when absent"); + } + + #[test] + fn fixture_with_info_still_parses() { + let json = fixture_json(true); + let tests: Tests = serde_json::from_str(&json).expect("must parse with _info"); + assert_eq!(tests.0.len(), 1); + let info = tests.0[0]._info.as_ref().expect("_info should be Some when present"); + assert_eq!(info.comment.as_deref(), Some("goevmlab-generated")); + } +} From 5aef1bfaedd6b74e699fb46b7af0df816021bf1a Mon Sep 17 00:00:00 2001 From: Esteban Dimitroff Hodi Date: Fri, 22 May 2026 15:40:42 -0300 Subject: [PATCH 2/4] fix(l1): apply EF state-test BLOCKHASH convention in statetest harness --- .../ef_tests/state_v2/src/modules/utils.rs | 116 +++++++++++++++++- 1 file changed, 113 insertions(+), 3 deletions(-) diff --git a/tooling/ef_tests/state_v2/src/modules/utils.rs b/tooling/ef_tests/state_v2/src/modules/utils.rs index 1b05c266d41..bb895c34e53 100644 --- a/tooling/ef_tests/state_v2/src/modules/utils.rs +++ b/tooling/ef_tests/state_v2/src/modules/utils.rs @@ -1,10 +1,13 @@ use ethrex_blockchain::vm::StoreVmDatabase; use ethrex_common::H256; use ethrex_common::{ - U256, - types::{Fork, Genesis}, + Address, U256, + types::{AccountState, ChainConfig, Code, CodeMetadata, Fork, Genesis}, + utils::keccak, }; +use ethrex_levm::db::Database as LevmDatabase; use ethrex_levm::db::gen_db::GeneralizedDatabase; +use ethrex_levm::errors::DatabaseError; use ethrex_storage::{EngineType, Store}; use ethrex_vm::DynVmDatabase; @@ -15,6 +18,45 @@ use crate::modules::{ types::{Env, Test, TestCase, genesis_from_test_and_fork}, }; +/// Wraps an inner levm `Database` to enforce the EF state-test convention for +/// `BLOCKHASH(n)` = `keccak256(decimal_string(n))`, independent of underlying +/// storage. Matches geth's `vmTestBlockHash` in `tests/state_test_util.go`. +/// +/// Without this override BLOCKHASH(0) at block 1 returns the genesis hash that +/// ethrex derives from the test's pre-state, which doesn't match the hash +/// fixtures put in `env.previousHash` (the EF convention). That trips +/// differential fuzzers like goevmlab on the very first block-hash lookup. +pub struct StatetestDatabase { + inner: Arc, +} + +impl StatetestDatabase { + pub fn new(inner: Arc) -> Self { + Self { inner } + } +} + +impl LevmDatabase for StatetestDatabase { + fn get_account_state(&self, address: Address) -> Result { + self.inner.get_account_state(address) + } + fn get_storage_value(&self, address: Address, key: H256) -> Result { + self.inner.get_storage_value(address, key) + } + fn get_block_hash(&self, block_number: u64) -> Result { + Ok(keccak(block_number.to_string().as_bytes())) + } + fn get_chain_config(&self) -> Result { + self.inner.get_chain_config() + } + fn get_account_code(&self, code_hash: H256) -> Result { + self.inner.get_account_code(code_hash) + } + fn get_code_metadata(&self, code_hash: H256) -> Result { + self.inner.get_code_metadata(code_hash) + } +} + /// Calculates the price of the gas based on the fields the test case has. For transaction types /// previous to EIP1559, the gas_price is explicit in the test. For later transaction types, it requires /// to be calculated based on `current_base_fee`, `priority_fee` and `max_fee_per_gas` values. @@ -47,12 +89,80 @@ pub async fn load_initial_state( let block_hash = genesis.get_block().hash(); let store: DynVmDatabase = Box::new(StoreVmDatabase::new(storage.clone(), genesis.get_block().header).unwrap()); + let inner: Arc = Arc::new(store); + let wrapped: Arc = Arc::new(StatetestDatabase::new(inner)); // We return some values that will be needed to calculate the post execution checks (original storage, genesis and blockhash) ( - GeneralizedDatabase::new(Arc::new(store)), + GeneralizedDatabase::new(wrapped), block_hash, storage, genesis, ) } + +#[cfg(test)] +mod tests { + use super::*; + use std::str::FromStr; + + /// Minimal LevmDatabase stub that returns a sentinel block hash, so the + /// test can assert that `StatetestDatabase` overrides BLOCKHASH and never + /// consults the inner DB for it. + struct SentinelInner; + impl LevmDatabase for SentinelInner { + fn get_account_state(&self, _: Address) -> Result { + unreachable!("not exercised by BLOCKHASH test") + } + fn get_storage_value(&self, _: Address, _: H256) -> Result { + unreachable!("not exercised by BLOCKHASH test") + } + fn get_block_hash(&self, _: u64) -> Result { + // If the wrapper ever delegates BLOCKHASH downward, this sentinel + // proves the bug — the override path is the only correct answer. + Ok(H256::repeat_byte(0xff)) + } + fn get_chain_config(&self) -> Result { + unreachable!("not exercised by BLOCKHASH test") + } + fn get_account_code(&self, _: H256) -> Result { + unreachable!("not exercised by BLOCKHASH test") + } + fn get_code_metadata(&self, _: H256) -> Result { + unreachable!("not exercised by BLOCKHASH test") + } + } + + #[test] + fn blockhash_zero_matches_ef_convention() { + let db = StatetestDatabase::new(Arc::new(SentinelInner)); + // Per geth's vmTestBlockHash: keccak256("0"). + let expected = H256::from_str( + "0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", + ) + .unwrap(); + assert_eq!(db.get_block_hash(0).unwrap(), expected); + } + + #[test] + fn blockhash_nonzero_matches_ef_convention() { + let db = StatetestDatabase::new(Arc::new(SentinelInner)); + // keccak256("1") per geth's vmTestBlockHash. + let expected = H256::from_str( + "0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", + ) + .unwrap(); + assert_eq!(db.get_block_hash(1).unwrap(), expected); + } + + #[test] + fn blockhash_uses_decimal_not_hex() { + // Specifically pin the decimal-string convention. For n=10, ascii "10" + // and ascii "a" would hash to different values; we must use decimal. + let db = StatetestDatabase::new(Arc::new(SentinelInner)); + let got = db.get_block_hash(10).unwrap(); + let expected = keccak(b"10"); + assert_eq!(got, expected); + assert_ne!(got, keccak(b"a"), "must hash decimal string, not hex"); + } +} From 6b34c6171e06d0d25c7d2eb3b0939acc122dc92d Mon Sep 17 00:00:00 2001 From: Esteban Dimitroff Hodi Date: Fri, 22 May 2026 16:21:12 -0300 Subject: [PATCH 3/4] fix(l1): scope BLOCKHASH override and propagate Osaka through statetest paths --- .../state_v2/src/modules/block_runner.rs | 31 +++++++++++++++---- .../ef_tests/state_v2/src/modules/runner.rs | 18 ++++++----- .../state_v2/src/modules/statetest.rs | 2 +- .../ef_tests/state_v2/src/modules/types.rs | 6 +++- .../ef_tests/state_v2/src/modules/utils.rs | 27 +++++++++++++--- 5 files changed, 64 insertions(+), 20 deletions(-) diff --git a/tooling/ef_tests/state_v2/src/modules/block_runner.rs b/tooling/ef_tests/state_v2/src/modules/block_runner.rs index f0c58c2c9d5..fe380c8d1be 100644 --- a/tooling/ef_tests/state_v2/src/modules/block_runner.rs +++ b/tooling/ef_tests/state_v2/src/modules/block_runner.rs @@ -23,7 +23,26 @@ use crate::modules::{ }; pub async fn run_tests(tests: Vec) -> Result<(), RunnerError> { + // Fusaka EIPs that block-mode supports; mirrors the allowlist in runner.rs. + // TODO: drop once all Fusaka EIPs land. + let fusaka_eips_to_test: Vec<&str> = + vec!["eip-7594", "eip-7939", "eip-7918", "eip-7892", "eip-7883"]; + for test in &tests { + // Apply the same gating runner.rs uses so we don't unconditionally run + // every Osaka fixture in block mode. Fixtures without `_info` (e.g. + // goevmlab-generated) bypass the filter — we can't read the EIP list, + // so silently dropping them would be wrong. + if test.path.to_str().unwrap().contains("osaka") + && let Some(spec) = test + ._info + .as_ref() + .and_then(|info| info.reference_spec.as_deref()) + && !fusaka_eips_to_test.iter().any(|eip| spec.contains(eip)) + { + continue; + } + println!("Running test group: {}", test.name); for test_case in &test.test_cases { let res = run_test(test, test_case).await; @@ -43,7 +62,7 @@ pub async fn run_test(test: &Test, test_case: &TestCase) -> Result<(), RunnerErr let tracer = LevmCallTracer::disabled(); let (mut db, initial_block_hash, store, _genesis) = - load_initial_state(test, &test_case.fork).await; + load_initial_state(test, &test_case.fork, false).await; let mut vm = VM::new(env.clone(), &mut db, &tx, tracer, VMType::L1, &NativeCrypto) .map_err(RunnerError::VMError)?; let execution_result = vm.execute(); @@ -81,7 +100,7 @@ pub async fn run_test(test: &Test, test_case: &TestCase) -> Result<(), RunnerErr // So they could be specified in the test but if the fork is e.g. Paris we should set them to None despite that. // Otherwise it will fail block header validations let (excess_blob_gas, blob_gas_used, parent_beacon_block_root, requests_hash) = match fork { - Fork::Prague | Fork::Cancun => { + Fork::Cancun | Fork::Prague | Fork::Osaka => { let blob_gas_used = match tx { Transaction::EIP4844Transaction(blob_tx) => { Some(get_total_blob_gas(&blob_tx) as u64) @@ -97,10 +116,10 @@ pub async fn run_test(test: &Test, test_case: &TestCase) -> Result<(), RunnerErr .unwrap(), ); let parent_beacon_block_root = Some(H256::zero()); - let requests_hash = if fork == Fork::Prague { - Some(*DEFAULT_REQUESTS_HASH) - } else { - None + // Prague added requests; Osaka inherits the same mechanism. + let requests_hash = match fork { + Fork::Prague | Fork::Osaka => Some(*DEFAULT_REQUESTS_HASH), + _ => None, }; ( excess_blob_gas, diff --git a/tooling/ef_tests/state_v2/src/modules/runner.rs b/tooling/ef_tests/state_v2/src/modules/runner.rs index c02d832b2b6..9ed8b637001 100644 --- a/tooling/ef_tests/state_v2/src/modules/runner.rs +++ b/tooling/ef_tests/state_v2/src/modules/runner.rs @@ -37,14 +37,16 @@ pub async fn run_tests(tests: Vec) -> Result<(), RunnerError> { vec!["eip-7594", "eip-7939", "eip-7918", "eip-7892", "eip-7883"]; for test in tests { - let test_eip = test - ._info - .as_ref() - .and_then(|info| info.reference_spec.clone()) - .unwrap_or_default(); - + // Fusaka EIP allowlist only applies when `_info.reference_spec` is + // present. Fixtures without it (e.g. goevmlab-generated) bypass the + // filter so they aren't silently dropped just because we can't read + // the EIP list. if test.path.to_str().unwrap().contains("osaka") - && !fusaka_eips_to_test.iter().any(|eip| test_eip.contains(eip)) + && let Some(spec) = test + ._info + .as_ref() + .and_then(|info| info.reference_spec.as_deref()) + && !fusaka_eips_to_test.iter().any(|eip| spec.contains(eip)) { continue; } @@ -70,7 +72,7 @@ pub async fn run_test( for test_case in &test.test_cases { // Setup VM for transaction. let (mut db, initial_block_hash, storage, genesis) = - load_initial_state(test, &test_case.fork).await; + load_initial_state(test, &test_case.fork, true).await; let env = get_vm_env_for_test(test.env, test_case)?; let tx = get_tx_from_test_case(test_case).await?; let tracer = LevmCallTracer::disabled(); diff --git a/tooling/ef_tests/state_v2/src/modules/statetest.rs b/tooling/ef_tests/state_v2/src/modules/statetest.rs index ee13424b392..9e195496ed0 100644 --- a/tooling/ef_tests/state_v2/src/modules/statetest.rs +++ b/tooling/ef_tests/state_v2/src/modules/statetest.rs @@ -90,7 +90,7 @@ async fn run_case( emit_trace: bool, ) -> Result { let (mut db, initial_block_hash, storage, _genesis) = - load_initial_state(test, &test_case.fork).await; + load_initial_state(test, &test_case.fork, true).await; let env = get_vm_env_for_test(test.env, test_case)?; let tx = get_tx_from_test_case(test_case).await?; diff --git a/tooling/ef_tests/state_v2/src/modules/types.rs b/tooling/ef_tests/state_v2/src/modules/types.rs index b9d74cb48a7..b934b9cca61 100644 --- a/tooling/ef_tests/state_v2/src/modules/types.rs +++ b/tooling/ef_tests/state_v2/src/modules/types.rs @@ -226,7 +226,9 @@ impl Tests { pub struct Test { pub name: String, // The name of the test object inside the .json file. pub path: PathBuf, // The path of the .json file the Test can be found at. - pub _info: Option, // General information about the test (optional — present in EF fixtures, may be absent in goevmlab-generated ones). + /// General information about the test (optional — present in EF fixtures, + /// may be absent in goevmlab-generated ones). + pub _info: Option, pub env: Env, // The block enviroment before the test transaction happens. pub pre: HashMap, // The accounts state previous to the test transaction. pub test_cases: Vec, // A vector of specific cases to be tested under these conditions (transactions). @@ -295,6 +297,8 @@ pub fn genesis_from_test_and_fork(test: &Test, fork: &Fork) -> Genesis { schedule.cancun.target } else if *fork == Fork::Prague { schedule.prague.target + } else if *fork == Fork::Osaka { + schedule.osaka.target } else { 0 }; diff --git a/tooling/ef_tests/state_v2/src/modules/utils.rs b/tooling/ef_tests/state_v2/src/modules/utils.rs index bb895c34e53..a886f85cb79 100644 --- a/tooling/ef_tests/state_v2/src/modules/utils.rs +++ b/tooling/ef_tests/state_v2/src/modules/utils.rs @@ -26,12 +26,19 @@ use crate::modules::{ /// ethrex derives from the test's pre-state, which doesn't match the hash /// fixtures put in `env.previousHash` (the EF convention). That trips /// differential fuzzers like goevmlab on the very first block-hash lookup. -pub struct StatetestDatabase { +/// +/// Scoped to single-pass executions (`statetest` CLI + `runner.rs` EF runner). +/// `block_runner.rs` deliberately does NOT use this shim — its phase-3 real +/// import goes through `add_block_pipeline` which would not honor the override, +/// so applying the shim only to its phase-1 pre-exec would make the two phases +/// disagree on BLOCKHASH. Closing block_runner's BLOCKHASH gap end-to-end is +/// a separate fix. +pub(crate) struct StatetestDatabase { inner: Arc, } impl StatetestDatabase { - pub fn new(inner: Arc) -> Self { + pub(crate) fn new(inner: Arc) -> Self { Self { inner } } } @@ -77,9 +84,17 @@ pub fn effective_gas_price(test_env: &Env, test_case: &TestCase) -> Result (GeneralizedDatabase, H256, Store, Genesis) { let genesis = genesis_from_test_and_fork(test, fork); let mut storage = Store::new("./temp", EngineType::InMemory).expect("Failed to create Store"); @@ -90,11 +105,15 @@ pub async fn load_initial_state( let store: DynVmDatabase = Box::new(StoreVmDatabase::new(storage.clone(), genesis.get_block().header).unwrap()); let inner: Arc = Arc::new(store); - let wrapped: Arc = Arc::new(StatetestDatabase::new(inner)); + let db: Arc = if override_blockhash { + Arc::new(StatetestDatabase::new(inner)) + } else { + inner + }; // We return some values that will be needed to calculate the post execution checks (original storage, genesis and blockhash) ( - GeneralizedDatabase::new(wrapped), + GeneralizedDatabase::new(db), block_hash, storage, genesis, From f710899afdfd53048cbe4cb8a8dd25f4ca320027 Mon Sep 17 00:00:00 2001 From: Esteban Dimitroff Hodi Date: Fri, 22 May 2026 17:44:18 -0300 Subject: [PATCH 4/4] style: cargo fmt --- .../ef_tests/state_v2/src/modules/report.rs | 16 +++++---- .../ef_tests/state_v2/src/modules/types.rs | 35 +++++++++++++------ .../ef_tests/state_v2/src/modules/utils.rs | 21 ++++------- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/tooling/ef_tests/state_v2/src/modules/report.rs b/tooling/ef_tests/state_v2/src/modules/report.rs index 1881e83a98a..61da6dac90d 100644 --- a/tooling/ef_tests/state_v2/src/modules/report.rs +++ b/tooling/ef_tests/state_v2/src/modules/report.rs @@ -78,19 +78,21 @@ pub fn write_failing_test_to_report(test: &Test, failing_test_cases: Vec Some(serde_json::from_value(info_field.clone()).map_err(|err| { - serde::de::Error::custom(format!( - "Failed to deserialize `info` field in test {}. Serde error: {}", - test_name, err - )) - })?), + Some(info_field) => { + Some(serde_json::from_value(info_field.clone()).map_err(|err| { + serde::de::Error::custom(format!( + "Failed to deserialize `info` field in test {}. Serde error: {}", + test_name, err + )) + })?) + } None => None, }; // Obtain the value of the `env` field in the JSON. @@ -229,7 +238,7 @@ pub struct Test { /// General information about the test (optional — present in EF fixtures, /// may be absent in goevmlab-generated ones). pub _info: Option, - pub env: Env, // The block enviroment before the test transaction happens. + pub env: Env, // The block enviroment before the test transaction happens. pub pre: HashMap, // The accounts state previous to the test transaction. pub test_cases: Vec, // A vector of specific cases to be tested under these conditions (transactions). } @@ -622,7 +631,10 @@ mod tests { let json = fixture_json(false); let tests: Tests = serde_json::from_str(&json).expect("must parse without _info"); assert_eq!(tests.0.len(), 1); - assert!(tests.0[0]._info.is_none(), "_info should be None when absent"); + assert!( + tests.0[0]._info.is_none(), + "_info should be None when absent" + ); } #[test] @@ -630,7 +642,10 @@ mod tests { let json = fixture_json(true); let tests: Tests = serde_json::from_str(&json).expect("must parse with _info"); assert_eq!(tests.0.len(), 1); - let info = tests.0[0]._info.as_ref().expect("_info should be Some when present"); + let info = tests.0[0] + ._info + .as_ref() + .expect("_info should be Some when present"); assert_eq!(info.comment.as_deref(), Some("goevmlab-generated")); } } diff --git a/tooling/ef_tests/state_v2/src/modules/utils.rs b/tooling/ef_tests/state_v2/src/modules/utils.rs index a886f85cb79..34d05415e8b 100644 --- a/tooling/ef_tests/state_v2/src/modules/utils.rs +++ b/tooling/ef_tests/state_v2/src/modules/utils.rs @@ -112,12 +112,7 @@ pub async fn load_initial_state( }; // We return some values that will be needed to calculate the post execution checks (original storage, genesis and blockhash) - ( - GeneralizedDatabase::new(db), - block_hash, - storage, - genesis, - ) + (GeneralizedDatabase::new(db), block_hash, storage, genesis) } #[cfg(test)] @@ -156,10 +151,9 @@ mod tests { fn blockhash_zero_matches_ef_convention() { let db = StatetestDatabase::new(Arc::new(SentinelInner)); // Per geth's vmTestBlockHash: keccak256("0"). - let expected = H256::from_str( - "0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", - ) - .unwrap(); + let expected = + H256::from_str("0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d") + .unwrap(); assert_eq!(db.get_block_hash(0).unwrap(), expected); } @@ -167,10 +161,9 @@ mod tests { fn blockhash_nonzero_matches_ef_convention() { let db = StatetestDatabase::new(Arc::new(SentinelInner)); // keccak256("1") per geth's vmTestBlockHash. - let expected = H256::from_str( - "0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6", - ) - .unwrap(); + let expected = + H256::from_str("0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6") + .unwrap(); assert_eq!(db.get_block_hash(1).unwrap(), expected); }