diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 2b48c4aef..e177e5a8e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -16,9 +16,9 @@ jobs: - name: Rustfmt run: cargo fmt --all -- --check - name: Clippy - run: cargo clippy --all-targets -- -D clippy::all -D clippy::nursery + run: cargo clippy --workspace --all-targets -- -D clippy::all -D clippy::nursery - name: Clippy no_std - run: cargo clippy --all-targets --no-default-features -- -D clippy::all -D clippy::nursery + run: cargo clippy --no-default-features -- -D clippy::all -D clippy::nursery build: runs-on: ubuntu-latest steps: @@ -26,9 +26,9 @@ jobs: - name: Build run: cargo build --verbose - name: Build NoStd - run: cargo build --no-default-features --verbose + run: cargo build --no-default-features - name: Build for feature (tracing) - run: cargo build --features tracing --verbose + run: cargo build --features tracing tests: runs-on: ubuntu-latest steps: @@ -37,3 +37,41 @@ jobs: submodules: recursive - name: Run tests run: cargo test --all --verbose + ethereum-tests: + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + with: + submodules: recursive + + - name: Checkout ethereum/tests + uses: actions/checkout@v4 + with: + repository: ethereum/tests + path: ethtests + ref: v13.2 + submodules: recursive + + - name: Run Ethereum state tests + run: | + cargo run -r -p evm-jsontests -F enable-slow-tests -- \ + state -f -s cancun \ + ethtests/GeneralStateTests/ + + - name: Run Ethereum vm tests + run: | + cargo run -r -p evm-jsontests -F enable-slow-tests -- \ + vm -f \ + ethtests/LegacyTests/Constantinople/VMTests/vmArithmeticTest \ + ethtests/LegacyTests/Constantinople/VMTests/vmBitwiseLogicOperation \ + ethtests/LegacyTests/Constantinople/VMTests/vmBlockInfoTest \ + ethtests/LegacyTests/Constantinople/VMTests/vmEnvironmentalInfo \ + ethtests/LegacyTests/Constantinople/VMTests/vmIOandFlowOperations \ + ethtests/LegacyTests/Constantinople/VMTests/vmLogTest \ + ethtests/LegacyTests/Constantinople/VMTests/vmPerformance \ + ethtests/LegacyTests/Constantinople/VMTests/vmPushDupSwapTest \ + ethtests/LegacyTests/Constantinople/VMTests/vmRandomTest \ + ethtests/LegacyTests/Constantinople/VMTests/vmSha3Test \ + ethtests/LegacyTests/Constantinople/VMTests/vmSystemOperations \ + ethtests/LegacyTests/Constantinople/VMTests/vmTests diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index fdf0eb5eb..000000000 --- a/.gitmodules +++ /dev/null @@ -1,4 +0,0 @@ -[submodule "evm-tests/jsontests/res/ethtests"] - path = evm-tests/jsontests/res/ethtests - url = https://github.com/ethereum/tests - tag = v13.2 diff --git a/Cargo.toml b/Cargo.toml index 33da99512..87a41a33b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "evm" -version = "0.41.0" +version = "0.42.0" license = "Apache-2.0" authors = ["Wei Tang ", "Parity Technologies "] description = "SputnikVM - a Portable Blockchain Virtual Machine" repository = "https://github.com/sorpaas/rust-evm" keywords = ["no_std", "ethereum"] -edition = "2018" +edition = "2021" [dependencies] auto_impl = "1.0" @@ -19,12 +19,12 @@ sha3 = { version = "0.10", default-features = false } # Optional dependencies environmental = { version = "1.1.2", default-features = false, optional = true } scale-codec = { package = "parity-scale-codec", version = "3.2", default-features = false, features = ["derive"], optional = true } -scale-info = { version = "2.3", default-features = false, features = ["derive"], optional = true } +scale-info = { version = "2.11", default-features = false, features = ["derive"], optional = true } serde = { version = "1.0", default-features = false, features = ["derive"], optional = true } -evm-core = { version = "0.41", path = "core", default-features = false } -evm-gasometer = { version = "0.41", path = "gasometer", default-features = false } -evm-runtime = { version = "0.41", path = "runtime", default-features = false } +evm-core = { version = "0.42", path = "core", default-features = false } +evm-gasometer = { version = "0.42", path = "gasometer", default-features = false } +evm-runtime = { version = "0.42", path = "runtime", default-features = false } [dev-dependencies] criterion = "0.5" diff --git a/core/Cargo.toml b/core/Cargo.toml index 033083001..b762447da 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -1,12 +1,12 @@ [package] name = "evm-core" -version = "0.41.0" +version = "0.42.0" license = "Apache-2.0" authors = ["Wei Tang ", "Parity Technologies "] description = "Portable Ethereum Virtual Machine implementation written in pure Rust." repository = "https://github.com/sorpaas/rust-evm" keywords = ["no_std", "ethereum"] -edition = "2018" +edition = "2021" [dependencies] log = { version = "0.4", optional = true } @@ -21,21 +21,21 @@ hex = "0.4" [features] default = ["std"] std = [ - "primitive-types/std", - "serde/std", - "scale-codec/std", - "scale-info/std", + "primitive-types/std", + "serde/std", + "scale-codec/std", + "scale-info/std", ] with-codec = [ - "scale-codec", - "scale-info", - "primitive-types/impl-codec", + "scale-codec", + "scale-info", + "primitive-types/impl-codec", ] with-serde = [ - "serde", - "primitive-types/impl-serde", + "serde", + "primitive-types/impl-serde", ] force-debug = [ - "log", + "log", ] tracing = [] diff --git a/evm-tests/jsontests/Cargo.toml b/evm-tests/jsontests/Cargo.toml index 6f232e735..c74f5aca2 100644 --- a/evm-tests/jsontests/Cargo.toml +++ b/evm-tests/jsontests/Cargo.toml @@ -15,7 +15,7 @@ primitive-types = "0.12" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" hex = "0.4" -clap = { version = "4.0", features = ["cargo"] } +clap = { version = "4.5", features = ["cargo"] } ethjson = { path = "../ethjson", features = ["test-helpers"] } libsecp256k1 = "0.7" ethcore-builtin = { path = "../ethcore-builtin" } @@ -24,3 +24,6 @@ sha3 = "0.10" parity-bytes = "0.1" env_logger = "0.11" lazy_static = "1.4.0" + +[features] +enable-slow-tests = [] diff --git a/evm-tests/jsontests/res/ethtests b/evm-tests/jsontests/res/ethtests deleted file mode 160000 index 066a5878d..000000000 --- a/evm-tests/jsontests/res/ethtests +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 066a5878da000bbf0ff95205c62a6c5c91ca6f52 diff --git a/evm-tests/jsontests/src/main.rs b/evm-tests/jsontests/src/main.rs index 4c46c9d39..6d6f6e39d 100644 --- a/evm-tests/jsontests/src/main.rs +++ b/evm-tests/jsontests/src/main.rs @@ -1,4 +1,4 @@ -use clap::{arg, command, value_parser, Arg, ArgAction, Command}; +use clap::{arg, command, value_parser, ArgAction, Command}; use ethjson::spec::ForkSpec; use evm_jsontests::state as statetests; use evm_jsontests::state::{TestExecutionResult, VerboseOutput}; @@ -10,22 +10,36 @@ use std::io::BufReader; use std::path::{Path, PathBuf}; #[allow(clippy::cognitive_complexity)] -fn main() { +fn main() -> Result<(), String> { let matches = command!() .version(env!("CARGO_PKG_VERSION")) .subcommand_required(true) .subcommand( - Command::new("vm").about("vm tests runner").arg( - Arg::new("PATH") - .help("json file or directory for tests run") - .required(true), - ), + Command::new("vm") + .about("vm tests runner") + .arg( + arg!([PATH] "json file or directory for tests run") + .action(ArgAction::Append) + .required(true) + .value_parser(value_parser!(PathBuf)), + ) + .arg( + arg!(-v --verbose "Verbose output") + .default_value("false") + .action(ArgAction::SetTrue), + ) + .arg( + arg!(-f --verbose_failed "Verbose failed only output") + .default_value("false") + .action(ArgAction::SetTrue), + ), ) .subcommand( Command::new("state") .about("state tests runner") .arg( arg!([PATH] "json file or directory for tests run") + .action(ArgAction::Append) .required(true) .value_parser(value_parser!(PathBuf)), ) @@ -54,17 +68,27 @@ fn main() { .get_matches(); if let Some(matches) = matches.subcommand_matches("vm") { - for file_name in matches.get_many::("PATH").unwrap() { - let file = File::open(file_name).expect("Open failed"); - - let reader = BufReader::new(file); - let test_suite = serde_json::from_reader::<_, HashMap>(reader) - .expect("Parse test cases failed"); - - for (name, test) in test_suite { - vmtests::test(&name, test); + let verbose_output = VerboseOutput { + verbose: matches.get_flag("verbose"), + verbose_failed: matches.get_flag("verbose_failed"), + very_verbose: false, + print_state: false, + }; + let mut tests_result = TestExecutionResult::new(); + for src_name in matches.get_many::("PATH").unwrap() { + let path = Path::new(src_name); + assert!(path.exists(), "data source is not exist"); + if path.is_file() { + run_vm_test_for_file(&verbose_output, path, &mut tests_result); + } else if path.is_dir() { + run_vm_test_for_dir(&verbose_output, path, &mut tests_result); } } + println!("\nTOTAL: {}", tests_result.total); + println!("FAILED: {}\n", tests_result.failed); + if tests_result.failed != 0 { + return Err(format!("tests failed: {}", tests_result.failed)); + } } if let Some(matches) = matches.subcommand_matches("state") { @@ -90,6 +114,79 @@ fn main() { } println!("\nTOTAL: {}", tests_result.total); println!("FAILED: {}\n", tests_result.failed); + if tests_result.failed != 0 { + return Err(format!("tests failed: {}", tests_result.failed)); + } + } + Ok(()) +} + +fn run_vm_test_for_dir( + verbose_output: &VerboseOutput, + dir_name: &Path, + tests_result: &mut TestExecutionResult, +) { + for entry in fs::read_dir(dir_name).unwrap() { + let entry = entry.unwrap(); + if let Some(s) = entry.file_name().to_str() { + if s.starts_with('.') { + continue; + } + } + let path = entry.path(); + if path.is_dir() { + run_vm_test_for_dir(verbose_output, path.as_path(), tests_result); + } else { + run_vm_test_for_file(verbose_output, path.as_path(), tests_result); + } + } +} + +fn run_vm_test_for_file( + verbose_output: &VerboseOutput, + file_name: &Path, + tests_result: &mut TestExecutionResult, +) { + if verbose_output.verbose { + println!( + "RUN for: {}", + short_test_file_name(file_name.to_str().unwrap()) + ); + } + let file = File::open(file_name).expect("Open file failed"); + + let reader = BufReader::new(file); + let test_suite = serde_json::from_reader::<_, HashMap>(reader) + .expect("Parse test cases failed"); + + for (name, test) in test_suite { + let test_res = vmtests::test(verbose_output, &name, test); + + if test_res.failed > 0 { + if verbose_output.verbose { + println!("Tests count:\t{}", test_res.total); + println!( + "Failed:\t\t{} - {}\n", + test_res.failed, + short_test_file_name(file_name.to_str().unwrap()) + ); + } else if verbose_output.verbose_failed { + println!( + "RUN for: {}", + short_test_file_name(file_name.to_str().unwrap()) + ); + println!("Tests count:\t{}", test_res.total); + println!( + "Failed:\t\t{} - {}\n", + test_res.failed, + short_test_file_name(file_name.to_str().unwrap()) + ); + } + } else if verbose_output.verbose { + println!("Tests count: {}\n", test_res.total); + } + + tests_result.merge(test_res); } } @@ -183,21 +280,29 @@ fn short_test_file_name(name: &str) -> String { } } +#[cfg(feature = "enable-slow-tests")] +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", +]; + +#[cfg(not(feature = "enable-slow-tests"))] 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", // These tests are passing, but they take a lot of time to execute so can going to skip them. - // NOTE: do not remove it to know slowest tests. It's useful for development. - // "stTimeConsuming/static_Call50000_sha256", - // "vmPerformance/loopMul", - // "stTimeConsuming/CALLBlake2f_MaxRounds", + "stTimeConsuming/static_Call50000_sha256", + "vmPerformance/loopMul", + "stTimeConsuming/CALLBlake2f_MaxRounds", ]; /// Check if a path should be skipped. /// It checks: -/// - path/and_file_stam - check path and file name (without extention) +/// - path/and_file_stem - check path and file name (without extention) /// - path/with/sub/path - recursively check path fn should_skip(path: &Path) -> bool { let matches = |case: &str| { diff --git a/evm-tests/jsontests/src/state.rs b/evm-tests/jsontests/src/state.rs index 062904f1d..d5df9d258 100644 --- a/evm-tests/jsontests/src/state.rs +++ b/evm-tests/jsontests/src/state.rs @@ -675,7 +675,7 @@ fn test_run( let h = states.first().unwrap().hash.0; // if vicinity could not be computed then the transaction was invalid so we simply // check the original state and move on - let (is_valid_hash, actual_hash) = crate::utils::assert_valid_hash(&h, &original_state); + let (is_valid_hash, actual_hash) = crate::utils::check_valid_hash(&h, &original_state); if !is_valid_hash { tests_result.failed_tests.push(FailedTestDetails { expected_hash: h, @@ -860,7 +860,7 @@ fn test_run( panic!("unexpected validation for test {name}-{i}") } let (is_valid_hash, actual_hash) = - crate::utils::assert_valid_hash(&state.hash.0, backend.state()); + crate::utils::check_valid_hash(&state.hash.0, backend.state()); if !is_valid_hash { let failed_res = FailedTestDetails { expected_hash: state.hash.0, @@ -902,7 +902,7 @@ fn test_run( } } } else if verbose_output.very_verbose && !verbose_output.verbose_failed { - println!(" [{:?}] {}:{} ... passed", spec, name, i); + println!(" [{spec:?}] {name}:{i} ... passed"); } } } diff --git a/evm-tests/jsontests/src/utils.rs b/evm-tests/jsontests/src/utils.rs index 7d26c3ae0..50ebef515 100644 --- a/evm-tests/jsontests/src/utils.rs +++ b/evm-tests/jsontests/src/utils.rs @@ -102,26 +102,7 @@ impl rlp::Decodable for TrieAccount { } } -pub fn assert_valid_state(a: ðjson::spec::State, b: &BTreeMap) { - match &a.0 { - ethjson::spec::HashOrMap::Map(m) => { - assert_eq!( - &m.iter() - .map(|(k, v)| { ((*k).into(), unwrap_to_account(v)) }) - .collect::>(), - b - ); - } - ethjson::spec::HashOrMap::Hash(h) => { - let x = assert_valid_hash(&(*h).into(), b); - if !x.0 { - panic!("Wrong hash: {:#x?}", x.1); - } - } - } -} - -pub fn assert_valid_hash(h: &H256, b: &BTreeMap) -> (bool, H256) { +pub fn check_valid_hash(h: &H256, b: &BTreeMap) -> (bool, H256) { let tree = b .iter() .map(|(address, account)| { diff --git a/evm-tests/jsontests/src/vm.rs b/evm-tests/jsontests/src/vm.rs index f8ab506dd..8a0f96513 100644 --- a/evm-tests/jsontests/src/vm.rs +++ b/evm-tests/jsontests/src/vm.rs @@ -1,4 +1,4 @@ -use crate::utils::*; +use crate::state::{TestExecutionResult, VerboseOutput}; use evm::backend::{ApplyBackend, MemoryAccount, MemoryBackend, MemoryVicinity}; use evm::executor::stack::{MemoryStackState, StackExecutor, StackSubstateMetadata}; use evm::Config; @@ -11,11 +11,11 @@ use std::rc::Rc; pub struct Test(ethjson::vm::Vm); impl Test { - pub fn unwrap_to_pre_state(&self) -> BTreeMap { - unwrap_to_state(&self.0.pre_state) + fn unwrap_to_pre_state(&self) -> BTreeMap { + crate::utils::unwrap_to_state(&self.0.pre_state) } - pub fn unwrap_to_vicinity(&self) -> MemoryVicinity { + fn unwrap_to_vicinity(&self) -> MemoryVicinity { let block_randomness = self.0.env.random.map(|r| { // Convert between U256 and H256. U256 is in little-endian but since H256 is just // a string-like byte array, it's big endian (MSB is the first element of the array). @@ -47,15 +47,15 @@ impl Test { } } - pub fn unwrap_to_code(&self) -> Rc> { + fn unwrap_to_code(&self) -> Rc> { Rc::new(self.0.transaction.code.clone().into()) } - pub fn unwrap_to_data(&self) -> Rc> { + fn unwrap_to_data(&self) -> Rc> { Rc::new(self.0.transaction.data.clone().into()) } - pub fn unwrap_to_context(&self) -> evm::Context { + fn unwrap_to_context(&self) -> evm::Context { evm::Context { address: self.0.transaction.address.into(), caller: self.0.transaction.sender.into(), @@ -63,22 +63,43 @@ impl Test { } } - pub fn unwrap_to_return_value(&self) -> Vec { + fn unwrap_to_return_value(&self) -> Vec { self.0.output.clone().unwrap().into() } - pub fn unwrap_to_gas_limit(&self) -> u64 { + fn unwrap_to_gas_limit(&self) -> u64 { self.0.transaction.gas.into() } - pub fn unwrap_to_post_gas(&self) -> u64 { + fn unwrap_to_post_gas(&self) -> u64 { self.0.gas_left.unwrap().into() } + + fn check_valid_state(&self, b: &BTreeMap) -> bool { + let post_state = self.0.post_state.as_ref().unwrap(); + match &post_state.0 { + ethjson::spec::HashOrMap::Map(m) => { + &m.iter() + .map(|(k, v)| ((*k).into(), crate::utils::unwrap_to_account(v))) + .collect::>() + == b + } + ethjson::spec::HashOrMap::Hash(h) => { + let x = crate::utils::check_valid_hash(&(*h).into(), b); + !x.0 + } + } + } } -pub fn test(name: &str, test: Test) { - print!("Running test {} ... ", name); - flush(); +pub fn test(verbose_output: &VerboseOutput, name: &str, test: Test) -> TestExecutionResult { + let mut result = TestExecutionResult::new(); + let mut failed = false; + result.total = 1; + if verbose_output.verbose { + print!("Running test {} ... ", name); + crate::utils::flush(); + } let original_state = test.unwrap_to_pre_state(); let vicinity = test.unwrap_to_vicinity(); @@ -101,21 +122,61 @@ pub fn test(name: &str, test: Test) { backend.apply(values, logs, false); if test.0.output.is_none() { - print!("{:?} ", reason); + if verbose_output.verbose { + print!("{:?} ", reason); + } - assert!(!reason.is_succeed()); - assert!(test.0.post_state.is_none() && test.0.gas_left.is_none()); + if reason.is_succeed() { + failed = true; + if verbose_output.verbose_failed { + print!("[Failed: succeed for empty output: {:?}] ", reason); + } + } + if !(test.0.post_state.is_none() && test.0.gas_left.is_none()) { + failed = true; + if verbose_output.verbose_failed { + print!( + "[Failed: not empty state and left gas for empty output: {:?}] ", + reason + ); + } + } } else { let expected_post_gas = test.unwrap_to_post_gas(); - print!("{:?} ", reason); - - assert_eq!( - runtime.machine().return_value(), - test.unwrap_to_return_value() - ); - assert_valid_state(test.0.post_state.as_ref().unwrap(), backend.state()); - assert_eq!(gas, expected_post_gas); + if verbose_output.verbose { + print!("{:?} ", reason); + } + + if runtime.machine().return_value() != test.unwrap_to_return_value() { + failed = true; + if verbose_output.verbose_failed { + print!( + "[Failed: wrong return value: {:?}] ", + runtime.machine().return_value() + ); + } + } + if !test.check_valid_state(backend.state()) { + failed = true; + if verbose_output.verbose_failed { + print!("[Failed: invalid state] "); + } + } + if gas != expected_post_gas { + failed = true; + if verbose_output.verbose_failed { + print!("[Failed: unexpected gas: {:?}] ", gas); + } + } } - println!("succeed"); + if failed { + result.failed += 1; + if verbose_output.verbose || verbose_output.verbose_failed { + println!("failed <-------"); + } + } else if verbose_output.verbose { + println!("succeed"); + } + result } diff --git a/evm-tests/jsontests/tests/state.rs b/evm-tests/jsontests/tests/state.rs deleted file mode 100644 index e0b909a58..000000000 --- a/evm-tests/jsontests/tests/state.rs +++ /dev/null @@ -1,367 +0,0 @@ -use ethjson::spec::ForkSpec; -use evm_jsontests::state as statetests; -use evm_jsontests::state::{TestExecutionResult, VerboseOutput}; -use std::fs::{self, File}; -use std::io::BufReader; -use std::path::PathBuf; -use std::{collections::HashMap, path::Path}; - -fn short_test_file_name(name: &str) -> String { - let res: Vec<_> = name.split("GeneralStateTests/").collect(); - if res.len() > 1 { - res[1].to_string() - } else { - res[0].to_string() - } -} - -pub fn run(dir: &str) { - const SPEC: Option = Some(ForkSpec::Cancun); - let _ = env_logger::try_init(); - - let mut dest = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - dest.push(dir); - - let mut tests_result = TestExecutionResult::new(); - let verbose_output = VerboseOutput { - verbose: false, - very_verbose: false, - verbose_failed: false, - print_state: false, - }; - for entry in fs::read_dir(dest).unwrap() { - let entry = entry.unwrap(); - if let Some(s) = entry.file_name().to_str() { - if s.starts_with('.') { - continue; - } - } - - let path = entry.path(); - let filename = path.to_str().unwrap(); - - if should_skip(&path) { - println!("Skipping test case {}", short_test_file_name(filename)); - continue; - } - - let file = File::open(&path).expect("Open file failed"); - - let reader = BufReader::new(file); - let test_suite: HashMap = serde_json::from_reader(reader) - .unwrap_or_else(|e| { - panic!("Parsing test case {:?} failed: {:?}", path, e); - }); - - for (name, test) in test_suite { - let test_res = statetests::test(verbose_output.clone(), &name, test, SPEC); - tests_result.merge(test_res); - } - } - println!("\nTOTAL: {}", tests_result.total); - println!("FAILED: {}\n", tests_result.failed); - assert_eq!(tests_result.failed, 0); -} - -// NOTE: Add a comment here explaining why you're skipping a test case. -const SKIPPED_CASES: &[&str] = &[ - // This is an expected failure case for testing that the VM rejects - // transactions with values that are too large, but it's geth - // specific because geth parses the hex string later in the test - // run, whereas this test runner parses everything up-front before - // running the test. - "stTransactionTest/ValueOverflow", - "stTransactionTest/ValueOverflowParis", -]; - -fn should_skip(path: &Path) -> bool { - let matches = |case: &str| { - let file_stem = path.file_stem().unwrap(); - let dir_path = path.parent().unwrap(); - let dir_name = dir_path.file_name().unwrap(); - Path::new(dir_name).join(file_stem) == Path::new(case) - }; - - for case in SKIPPED_CASES { - if matches(case) { - return true; - } - } - - false -} - -#[test] -fn st_args_zero_one_balance() { - run("res/ethtests/GeneralStateTests/stArgsZeroOneBalance") -} - -#[test] -fn st_attack() { - run("res/ethtests/GeneralStateTests/stAttackTest") -} - -#[test] -fn st_bad_opcode() { - run("res/ethtests/GeneralStateTests/stBadOpcode") -} - -#[test] -fn st_bugs() { - run("res/ethtests/GeneralStateTests/stBugs") -} - -#[test] -fn st_call_code() { - run("res/ethtests/GeneralStateTests/stCallCodes") -} - -#[test] -fn st_call_create_call_code() { - run("res/ethtests/GeneralStateTests/stCallCreateCallCodeTest") -} - -#[test] -fn st_call_delegate_codes_call_code_homestead() { - run("res/ethtests/GeneralStateTests/stCallDelegateCodesCallCodeHomestead") -} - -#[test] -fn st_call_delegate_codes_homestead() { - run("res/ethtests/GeneralStateTests/stCallDelegateCodesHomestead") -} - -#[test] -fn st_chain_id() { - run("res/ethtests/GeneralStateTests/stChainId") -} - -#[test] -fn st_code_copy() { - run("res/ethtests/GeneralStateTests/stCodeCopyTest") -} - -#[test] -fn st_code_size_limit() { - run("res/ethtests/GeneralStateTests/stCodeSizeLimit") -} - -#[test] -#[ignore] -fn st_create2() { - run("res/ethtests/GeneralStateTests/stCreate2") -} - -#[test] -fn st_create() { - run("res/ethtests/GeneralStateTests/stCreateTest") -} - -#[test] -fn st_delegate_call_homestead() { - run("res/ethtests/GeneralStateTests/stDelegatecallTestHomestead") -} - -#[test] -fn st_eip150_single_code_gas_prices() { - run("res/ethtests/GeneralStateTests/stEIP150singleCodeGasPrices") -} - -#[test] -fn st_eip150_specific() { - run("res/ethtests/GeneralStateTests/stEIP150Specific") -} - -#[test] -fn st_eip1559() { - run("res/ethtests/GeneralStateTests/stEIP1559") -} - -#[test] -fn st_eip158_specific() { - run("res/ethtests/GeneralStateTests/stEIP158Specific") -} - -#[test] -fn st_eip2930() { - run("res/ethtests/GeneralStateTests/stEIP2930") -} - -#[test] -fn st_example() { - run("res/ethtests/GeneralStateTests/stExample") -} - -#[test] -fn st_ext_code_hash() { - run("res/ethtests/GeneralStateTests/stExtCodeHash") -} - -#[test] -fn st_homestead_specific() { - run("res/ethtests/GeneralStateTests/stHomesteadSpecific") -} - -#[test] -fn st_init_code() { - run("res/ethtests/GeneralStateTests/stInitCodeTest") -} - -#[test] -fn st_log() { - run("res/ethtests/GeneralStateTests/stLogTests") -} - -#[test] -fn st_mem_expanding_eip_150_calls() { - run("res/ethtests/GeneralStateTests/stMemExpandingEIP150Calls") -} - -#[test] -fn st_memory_stress() { - run("res/ethtests/GeneralStateTests/stMemoryStressTest") -} - -#[test] -fn st_memory() { - run("res/ethtests/GeneralStateTests/stMemoryTest") -} - -#[test] -fn st_non_zero_calls() { - run("res/ethtests/GeneralStateTests/stNonZeroCallsTest") -} - -#[test] -fn st_precompiled_contracts() { - run("res/ethtests/GeneralStateTests/stPreCompiledContracts") -} - -#[test] -#[ignore] -fn st_precompiled_contracts2() { - run("res/ethtests/GeneralStateTests/stPreCompiledContracts2") -} - -#[test] -#[ignore] -fn st_quadratic_complexity() { - run("res/ethtests/GeneralStateTests/stQuadraticComplexityTest") -} - -#[test] -fn st_random() { - run("res/ethtests/GeneralStateTests/stRandom") -} - -#[test] -fn st_random2() { - run("res/ethtests/GeneralStateTests/stRandom2") -} - -#[test] -fn st_recursive_create() { - run("res/ethtests/GeneralStateTests/stRecursiveCreate") -} - -#[test] -fn st_refund() { - run("res/ethtests/GeneralStateTests/stRefundTest") -} - -#[test] -fn st_return_data() { - run("res/ethtests/GeneralStateTests/stReturnDataTest") -} - -#[test] -#[ignore] -fn st_revert() { - run("res/ethtests/GeneralStateTests/stRevertTest") -} - -#[test] -fn st_self_balance() { - run("res/ethtests/GeneralStateTests/stSelfBalance") -} - -#[test] -fn st_shift() { - run("res/ethtests/GeneralStateTests/stShift") -} - -#[test] -fn st_sload() { - run("res/ethtests/GeneralStateTests/stSLoadTest") -} - -#[test] -fn st_solidity() { - run("res/ethtests/GeneralStateTests/stSolidityTest") -} - -#[test] -#[ignore] -fn st_special() { - run("res/ethtests/GeneralStateTests/stSpecialTest") -} - -// Some of the collison test in sstore conflicts with evm's internal -// handlings. Those situations will never happen on a production chain (an empty -// account with storage values), so we can safely ignore them. -#[test] -#[ignore] -fn st_sstore() { - run("res/ethtests/GeneralStateTests/stSStoreTest") -} - -#[test] -fn st_stack() { - run("res/ethtests/GeneralStateTests/stStackTests") -} - -#[test] -#[ignore] -fn st_static_call() { - run("res/ethtests/GeneralStateTests/stStaticCall") -} - -#[test] -fn st_system_operations() { - run("res/ethtests/GeneralStateTests/stSystemOperationsTest") -} - -#[test] -fn st_transaction() { - run("res/ethtests/GeneralStateTests/stTransactionTest") -} - -#[test] -fn st_transition() { - run("res/ethtests/GeneralStateTests/stTransitionTest") -} - -#[test] -fn st_wallet() { - run("res/ethtests/GeneralStateTests/stWalletTest") -} - -#[test] -fn st_zero_calls_revert() { - run("res/ethtests/GeneralStateTests/stZeroCallsRevert"); -} - -#[test] -fn st_zero_calls() { - run("res/ethtests/GeneralStateTests/stZeroCallsTest") -} - -#[test] -fn st_zero_knowledge() { - run("res/ethtests/GeneralStateTests/stZeroKnowledge") -} - -#[test] -fn st_zero_knowledge2() { - run("res/ethtests/GeneralStateTests/stZeroKnowledge2") -} diff --git a/evm-tests/jsontests/tests/vm.rs b/evm-tests/jsontests/tests/vm.rs deleted file mode 100644 index 8291a536a..000000000 --- a/evm-tests/jsontests/tests/vm.rs +++ /dev/null @@ -1,78 +0,0 @@ -use evm_jsontests::vm as vmtests; -use std::collections::HashMap; -use std::fs::{self, File}; -use std::io::BufReader; -use std::path::PathBuf; - -pub fn run(dir: &str) { - let _ = env_logger::try_init(); - - let mut dest = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - dest.push(dir); - - for entry in fs::read_dir(dest).unwrap() { - let entry = entry.unwrap(); - let path = entry.path(); - - let file = File::open(path).expect("Open file failed"); - - let reader = BufReader::new(file); - let coll = serde_json::from_reader::<_, HashMap>(reader) - .expect("Parse test cases failed"); - - for (name, test) in coll { - vmtests::test(&name, test); - } - } -} - -// TODO: upgrade to GeneralStateTests/VMTests instead of using LegacyTests version -#[test] -fn vm_arithmetic() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmArithmeticTest"); -} -#[test] -fn vm_bitwise_logic() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmBitwiseLogicOperation"); -} -#[test] -fn vm_block_info() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmBlockInfoTest"); -} -#[test] -fn vm_environmental_info() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmEnvironmentalInfo"); -} -#[test] -fn vm_io_and_flow() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmIOandFlowOperations"); -} -#[test] -fn vm_log() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmLogTest"); -} -#[test] -#[ignore] -fn vm_performance() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmPerformance"); -} -#[test] -fn vm_push_dup_swap() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmPushDupSwapTest"); -} -#[test] -fn vm_random() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmRandomTest"); -} -#[test] -fn vm_sha3() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmSha3Test"); -} -#[test] -fn vm_system() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmSystemOperations"); -} -#[test] -fn vm_other() { - run("res/ethtests/LegacyTests/Constantinople/VMTests/vmTests"); -} diff --git a/fuzzer/Cargo.toml b/fuzzer/Cargo.toml index ecc1ff6dc..35300b1af 100644 --- a/fuzzer/Cargo.toml +++ b/fuzzer/Cargo.toml @@ -2,14 +2,14 @@ name = "evm-fuzzer" version = "0.2.0-dev" authors = ["Vincent Ulitzsch "] -edition = "2018" +edition = "2021" description = "Fuzzer for EVM." license = "Apache-2.0" [dependencies] honggfuzz = "0.5" -evm-core = { version = "0.41", path = "../core" } +evm-core = { version = "0.42", path = "../core" } [[bin]] name = "evm_fuzz" diff --git a/gasometer/Cargo.toml b/gasometer/Cargo.toml index 15fe09e4c..907d532f7 100644 --- a/gasometer/Cargo.toml +++ b/gasometer/Cargo.toml @@ -1,20 +1,20 @@ [package] name = "evm-gasometer" -version = "0.41.0" +version = "0.42.0" license = "Apache-2.0" authors = ["Wei Tang ", "Parity Technologies "] description = "Portable Ethereum Virtual Machine implementation written in pure Rust." repository = "https://github.com/sorpaas/rust-evm" keywords = ["no_std", "ethereum"] -edition = "2018" +edition = "2021" [dependencies] environmental = { version = "1.1.2", default-features = false, optional = true } log = { version = "0.4", optional = true } primitive-types = { version = "0.12", default-features = false } -evm-core = { version = "0.41", path = "../core", default-features = false } -evm-runtime = { version = "0.41", path = "../runtime", default-features = false } +evm-core = { version = "0.42", path = "../core", default-features = false } +evm-runtime = { version = "0.42", path = "../runtime", default-features = false } [features] default = ["std"] diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index e999fd490..c8f0bf548 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -1,29 +1,29 @@ [package] name = "evm-runtime" -version = "0.41.0" +version = "0.42.0" license = "Apache-2.0" authors = ["Wei Tang ", "Parity Technologies "] description = "SputnikVM - a Portable Blockchain Virtual Machine" repository = "https://github.com/sorpaas/rust-evm" keywords = ["no_std", "ethereum"] -edition = "2018" +edition = "2021" [dependencies] auto_impl = "1.0" -environmental = { version = "1.1.2", default-features = false, optional = true } +environmental = { version = "1.1", default-features = false, optional = true } primitive-types = { version = "0.12", default-features = false } sha3 = { version = "0.10", default-features = false } -evm-core = { version = "0.41", path = "../core", default-features = false } +evm-core = { version = "0.42", path = "../core", default-features = false } [features] default = ["std"] std = [ - "environmental/std", - "primitive-types/std", - "sha3/std", - "evm-core/std", + "environmental/std", + "primitive-types/std", + "sha3/std", + "evm-core/std", ] tracing = [ - "environmental", + "environmental", ]