diff --git a/crates/common/trie/trie.rs b/crates/common/trie/trie.rs index 6148f80234..3eafaf226b 100644 --- a/crates/common/trie/trie.rs +++ b/crates/common/trie/trie.rs @@ -261,6 +261,11 @@ impl Trie { all_nodes: &BTreeMap>, root_hash: H256, ) -> Result { + // If the root hash is of the empty trie then we can get away by setting the NodeRef to default + if root_hash == *EMPTY_TRIE_HASH { + return Ok(NodeRef::default()); + } + let root_rlp = all_nodes .get(&root_hash) .ok_or(TrieError::InconsistentTree)?; diff --git a/tooling/ef_tests/blockchain/test_runner.rs b/tooling/ef_tests/blockchain/test_runner.rs index eaee7ba433..d8d463e13f 100644 --- a/tooling/ef_tests/blockchain/test_runner.rs +++ b/tooling/ef_tests/blockchain/test_runner.rs @@ -30,39 +30,11 @@ pub fn parse_and_execute( ) -> datatest_stable::Result<()> { let rt = tokio::runtime::Runtime::new().unwrap(); let tests = parse_tests(path); - //Test with the Fusaka tests that should pass. TODO: Once we've implemented all the Fusaka EIPs this should be removed - //EIPs should be added as strings in the format 'eip-XXXX' - let fusaka_eips_to_test: Vec<&str> = vec![ - "eip-7594", "eip-7883", "eip-7918", "eip-7934", "eip-7892", "eip-7939", "eip-7951", - "eip-7594", "eip-7825", - ]; - - //Hashes of any other tests to run, that don't correspond to an especific EIP (for examples, some integration tests) - //We should really remove this once we're finished with implementing Fusaka, but it's a good-enough workaround to run specific tests for now - let hashes_of_fusaka_tests_to_run: Vec<&str> = vec![ - "0xf0672af9718013a1f396a9268e91e220ff09e7fa97480844e31da500f8ef291f", //All opcodes test - ]; - - // Names of tests to run, to run entire specific .json files. Checked against the TestUnit URl - let specific_fusaka_tests_to_run: Vec<&str> = vec![ - "/tests/frontier/precompiles/test_precompiles.py", - "/tests/frontier/precompiles/test_precompile_absence.py", - ]; let mut failures = Vec::new(); for (test_key, test) in tests { - let test_eip = test.info.clone().reference_spec.unwrap_or_default(); - let should_skip_test = test.network < Fork::Merge - || (test.network > Fork::Prague - && (!fusaka_eips_to_test.iter().any(|eip| test_eip.contains(eip)) - && !hashes_of_fusaka_tests_to_run - .iter() - .any(|hash| *hash == test.info.hash.clone().unwrap()) - && !specific_fusaka_tests_to_run - .iter() - .any(|name| test.info.url.clone().unwrap().contains(*name)))) || skipped_tests .map(|skipped| skipped.iter().any(|s| test_key.contains(s))) .unwrap_or(false); diff --git a/tooling/ef_tests/blockchain/tests/all.rs b/tooling/ef_tests/blockchain/tests/all.rs index 50318a3bcb..f135a264a2 100644 --- a/tooling/ef_tests/blockchain/tests/all.rs +++ b/tooling/ef_tests/blockchain/tests/all.rs @@ -1,63 +1,63 @@ use ef_tests_blockchain::test_runner::parse_and_execute; +use ethrex_prover_lib::backend::Backend; use std::path::Path; +// Enable only one of `sp1` or `stateless` at a time. +#[cfg(all(feature = "sp1", feature = "stateless"))] +compile_error!("Only one of `sp1` and `stateless` can be enabled at a time."); + const TEST_FOLDER: &str = "vectors/"; -#[cfg(not(any(feature = "sp1", feature = "stateless")))] -const SKIPPED_TESTS: &[&str] = &[ - "system_contract_deployment", - "HighGasPriceParis", // Skipped because it sets a gas price higher than u64::MAX, which most clients don't implement and is a virtually impossible scenario - "dynamicAccountOverwriteEmpty_Paris", // Skipped because the scenario described is virtually impossible - "create2collisionStorageParis", // Skipped because it's not worth implementing since the scenario of the test is virtually impossible. See https://github.com/lambdaclass/ethrex/issues/1555 - "RevertInCreateInInitCreate2Paris", // Skipped because it's not worth implementing since the scenario of the test is virtually impossible. See https://github.com/lambdaclass/ethrex/issues/1555 - "test_tx_gas_larger_than_block_gas_limit", - "createBlobhashTx", - "RevertInCreateInInit_Paris", +// Base skips shared by all runs. +const SKIPPED_BASE: &[&str] = &[ + // These tests contain accounts without nonce or code but have storage, which is a virtually impossible scenario. That's why we fail, but that's okay. + // When creating an account we don't check the storage root but just if it has nonce or code. + // Fix is on its way on https://github.com/lambdaclass/ethrex/pull/4813 "InitCollisionParis", - "ValueOverflowParis", -]; -// We are skipping test_tx_gas_larger_than_block_gas_limit[fork_Osaka-blockchain_test-exceed_block_gas_limit_True] because of an -// inconsistency on the expected exception. Exception returned is InvalidBlock(GasUsedMismatch(0x06000000,0x05000000)) while -// exception expected GAS_ALLOWANCE_EXCEEDED. The thing is gas allowance exception is supposed to be thrown on any transaction -// execution in case the transaction's gas limit is larger than the block's, which is not the case of this test. -// This test has a block with "gasLimit": "0x055d4a80", "gasUsed": "0x05000000" and six transactions with "gasLimit": "0x01000000", -// Apparently each transaction consumes up to its gas limit, which together is larger than the block's. Then when executing validate_gas_used -// after the block's execution, it throws InvalidBlock(GasUsedMismatch(0x06000000,0x05000000)) on comparing the receipt's cumulative gas used agains the block's gas limit. -#[cfg(any(feature = "sp1", feature = "stateless"))] -const SKIPPED_TESTS: &[&str] = &[ - // We skip most of these for the same reason we skip them in normal runs; since we need to do a normal run before running with the stateless backend - "system_contract_deployment", - "test_tx_gas_larger_than_block_gas_limit", - "HighGasPriceParis", - "dynamicAccountOverwriteEmpty_Paris", - "create2collisionStorageParis", "RevertInCreateInInitCreate2Paris", - "createBlobhashTx", + "create2collisionStorageParis", + "dynamicAccountOverwriteEmpty_Paris", "RevertInCreateInInit_Paris", - "InitCollisionParis", + // Skip because they take too long to run, but they pass + "static_Call50000_sha256", + "CALLBlake2f_MaxRounds", + "loopMul", + // Gas price higher than u64::MAX; impractical scenario. Fix is on its way on https://github.com/lambdaclass/ethrex/pull/4823 + "HighGasPriceParis", + // Skip because it tries to deserialize number > U256::MAX "ValueOverflowParis", - // We skip these two tests because they fail with stateless backend specifically. See https://github.com/lambdaclass/ethrex/issues/4502 - "test_large_amount", - "test_multiple_withdrawals_same_address", + // Skip because it's a "Create" Blob Transaction, which doesn't actually exist. It never reaches the EVM because we can't even parse it as an actual Transaction. + "createBlobhashTx", ]; +// Extra skips added only for prover backends. +#[cfg(feature = "sp1")] +const EXTRA_SKIPS: &[&str] = &[ + // I believe these tests fail because of how much stress they put into the zkVM, they probably cause an OOM though this should be checked + "static_Call50000", + "Return50000", + "static_Call1MB1024Calldepth", +]; +#[cfg(not(feature = "sp1"))] +const EXTRA_SKIPS: &[&str] = &[]; + +// Select backend +#[cfg(feature = "stateless")] +const BACKEND: Option = Some(Backend::Exec); +#[cfg(feature = "sp1")] +const BACKEND: Option = Some(Backend::SP1); #[cfg(not(any(feature = "sp1", feature = "stateless")))] -fn blockchain_runner(path: &Path) -> datatest_stable::Result<()> { - parse_and_execute(path, Some(SKIPPED_TESTS), None) -} +const BACKEND: Option = None; -// If `sp1` or `stateless` is enabled -#[cfg(any(feature = "sp1", feature = "stateless"))] fn blockchain_runner(path: &Path) -> datatest_stable::Result<()> { - #[cfg(feature = "stateless")] - let backend = Some(ethrex_prover_lib::backend::Backend::Exec); - #[cfg(feature = "sp1")] - let backend = Some(ethrex_prover_lib::backend::Backend::SP1); + // Compose the final skip list + let skips: Vec<&'static str> = SKIPPED_BASE + .iter() + .copied() + .chain(EXTRA_SKIPS.iter().copied()) + .collect(); - parse_and_execute(path, Some(SKIPPED_TESTS), backend) + parse_and_execute(path, Some(&skips), BACKEND) } datatest_stable::harness!(blockchain_runner, TEST_FOLDER, r".*"); - -#[cfg(any(all(feature = "sp1", feature = "stateless"),))] -compile_error!("Only one of `sp1` and `stateless` can be enabled at a time."); diff --git a/tooling/ef_tests/state/.gitignore b/tooling/ef_tests/state/.gitignore new file mode 100644 index 0000000000..03314f77b5 --- /dev/null +++ b/tooling/ef_tests/state/.gitignore @@ -0,0 +1 @@ +Cargo.lock diff --git a/tooling/ef_tests/state/parser.rs b/tooling/ef_tests/state/parser.rs index 9de8b622a3..40328e3133 100644 --- a/tooling/ef_tests/state/parser.rs +++ b/tooling/ef_tests/state/parser.rs @@ -20,7 +20,7 @@ pub enum EFTestParseError { FailedToParseTestFile(String), } -const IGNORED_TESTS: [&str; 11] = [ +const IGNORED_TESTS: &[&str] = &[ "static_Call50000_sha256.json", // Skip because it takes longer to run than some tests, but not a huge deal. "CALLBlake2f_MaxRounds.json", // Skip because it takes extremely long to run, but passes. "ValueOverflow.json", // Skip because it tries to deserialize number > U256::MAX diff --git a/tooling/ef_tests/state/runner/levm_runner.rs b/tooling/ef_tests/state/runner/levm_runner.rs index e8e5c781a8..9e3f762751 100644 --- a/tooling/ef_tests/state/runner/levm_runner.rs +++ b/tooling/ef_tests/state/runner/levm_runner.rs @@ -37,29 +37,7 @@ pub async fn run_ef_test(test: &EFTest) -> Result = vec![ - "eip-7594", "eip-7883", "eip-7918", "eip-7934", "eip-7892", "eip-7939", "eip-7951", - "eip-7594", "eip-7825", - ]; - - //Names of any other tests to run, that don't correspond to an especific EIP (for examples, some integration tests) - //We should really remove this once we're finished with implementing Fusaka, but it's a good-enough workaround to run specific tests for now - let names_of_fusaka_tests_to_run: Vec<&str> = vec![]; - - let test_eip = test._info.clone().reference_spec.unwrap_or_default(); - for fork in test.post.forks.keys() { - if fork == &Fork::Osaka - && !fusaka_eips_to_test.iter().any(|eip| test_eip.contains(eip)) - && !names_of_fusaka_tests_to_run - .iter() - .any(|name| *name == test.name) - { - continue; - } - let mut ef_test_report_fork = EFTestReportForkResult::new(); for (vector, _tx) in test.transactions.iter() { diff --git a/tooling/ef_tests/state_v2/src/modules/parser.rs b/tooling/ef_tests/state_v2/src/modules/parser.rs index 08c090a457..812208d99d 100644 --- a/tooling/ef_tests/state_v2/src/modules/parser.rs +++ b/tooling/ef_tests/state_v2/src/modules/parser.rs @@ -23,21 +23,27 @@ pub struct RunnerOptions { } //TODO: Use this constant, improve it. -const IGNORED_TESTS: [&str; 14] = [ - "static_Call50000_sha256.json", // Skip because it takes longer to run than some tests, but not a huge deal. - "CALLBlake2f_MaxRounds.json", // Skip because it takes extremely long to run, but passes. - "ValueOverflow.json", // Skip because it tries to deserialize number > U256::MAX - "ValueOverflowParis.json", // Skip because it tries to deserialize number > U256::MAX - "loopMul.json", // Skip because it takes too long to run +const IGNORED_TESTS: &[&str] = &[ + // These tests contain accounts without nonce or code but have storage, which is a virtually impossible scenario. That's why we fail, but that's okay. + // When creating an account we don't check the storage root but just if it has nonce or code, and that's the right check for real case scenarios. "dynamicAccountOverwriteEmpty_Paris.json", "RevertInCreateInInitCreate2Paris.json", "RevertInCreateInInit_Paris.json", "create2collisionStorageParis.json", "InitCollisionParis.json", "InitCollision.json", - "contract_create.json", // Skip for now as it requires special transaction type handling - "HighGasPrice.json", // Skip until we fix gas price unit (u64 -> U256) https://github.com/lambdaclass/ethrex/issues/3629 - "HighGasPriceParis.json", // Skip until we fix gas price unit (u64 -> U256) https://github.com/lambdaclass/ethrex/issues/3629 + // Gas price higher than u64::MAX; impractical scenario. We don't use 256 bits for gas price for performance reasons, however, it's debatable. See https://github.com/lambdaclass/ethrex/issues/3629 + "HighGasPrice.json", + "HighGasPriceParis.json", + // Skip because they take too long to run, but they pass + "static_Call50000_sha256.json", + "CALLBlake2f_MaxRounds.json", + "loopMul.json", + // Skip because it tries to deserialize number > U256::MAX + "ValueOverflow.json", + "ValueOverflowParis.json", + // Skip for now as it requires special transaction type handling in test runner, we should improve that. + "contract_create.json", ]; /// Parse a `.json` file of tests into a Vec.