From 4ac605d9d0c3794464178df3812cacee09dda773 Mon Sep 17 00:00:00 2001 From: Oleksandr Zarudnyi Date: Sun, 26 Jan 2025 13:00:16 +0800 Subject: [PATCH] feat(evm): support library linking (#135) --- Cargo.lock | 115 ++------- compiler_tester/Cargo.toml | 1 - compiler_tester/src/compiler_tester/main.rs | 2 +- compiler_tester/src/compilers/eravm/mod.rs | 2 +- compiler_tester/src/compilers/llvm/mod.rs | 5 +- compiler_tester/src/compilers/mod.rs | 2 +- compiler_tester/src/compilers/solidity/mod.rs | 9 +- .../src/compilers/solidity/upstream/mod.rs | 4 +- compiler_tester/src/compilers/vyper/mod.rs | 3 +- compiler_tester/src/compilers/yul/mod.rs | 4 +- .../src/directories/ethereum/test.rs | 2 +- .../matter_labs/test/metadata/case/mod.rs | 2 +- .../src/directories/matter_labs/test/mod.rs | 2 +- compiler_tester/src/lib.rs | 34 +-- .../src/test/case/input/balance.rs | 17 +- .../src/test/case/input/deploy_evm.rs | 51 +--- compiler_tester/src/test/case/input/mod.rs | 27 +- .../src/test/case/input/output/event.rs | 33 --- .../src/test/case/input/output/mod.rs | 31 --- .../src/test/case/input/runtime.rs | 49 +--- .../src/test/case/input/storage_empty.rs | 17 +- compiler_tester/src/test/case/mod.rs | 24 +- compiler_tester/src/test/mod.rs | 31 +-- compiler_tester/src/utils/mod.rs | 2 + compiler_tester/src/vm/evm/invoker.rs | 21 -- compiler_tester/src/vm/evm/mod.rs | 212 --------------- compiler_tester/src/vm/evm/output.rs | 28 -- compiler_tester/src/vm/evm/runtime.rs | 242 ------------------ compiler_tester/src/vm/execution_result.rs | 12 - compiler_tester/src/vm/mod.rs | 1 - .../src/vm/{evm => revm}/address_iterator.rs | 0 compiler_tester/src/vm/revm/balance.rs | 18 +- compiler_tester/src/vm/revm/init.rs | 45 +++- .../src/vm/{evm => revm}/input/build.rs | 0 .../src/vm/{evm => revm}/input/mod.rs | 0 compiler_tester/src/vm/revm/mod.rs | 205 ++++++++++++++- 36 files changed, 318 insertions(+), 935 deletions(-) delete mode 100644 compiler_tester/src/vm/evm/invoker.rs delete mode 100644 compiler_tester/src/vm/evm/mod.rs delete mode 100644 compiler_tester/src/vm/evm/output.rs delete mode 100644 compiler_tester/src/vm/evm/runtime.rs rename compiler_tester/src/vm/{evm => revm}/address_iterator.rs (100%) rename compiler_tester/src/vm/{evm => revm}/input/build.rs (100%) rename compiler_tester/src/vm/{evm => revm}/input/mod.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 068057f0..84d0505b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -717,7 +717,6 @@ dependencies = [ "era-compiler-solidity", "era-compiler-vyper", "era-solc", - "evm", "glob", "hex", "inkwell", @@ -804,22 +803,13 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ba6d68e24814cb8de6bb986db8222d3a027d15872cabc0d18817bc3c0e4471" -dependencies = [ - "crossbeam-utils", -] - [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -847,9 +837,9 @@ checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" +checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" [[package]] name = "crypto-bigint" @@ -1103,7 +1093,7 @@ dependencies = [ [[package]] name = "era-compiler-llvm-context" version = "1.5.0" -source = "git+https://github.com/matter-labs/era-compiler-llvm-context?branch=main#564e41b4d9e0b6a3a0d2f875c6dd891477cef70c" +source = "git+https://github.com/matter-labs/era-compiler-llvm-context?branch=main#de72ad122ac3cd0f24a76eee889d08c85cc98f33" dependencies = [ "anyhow", "era-compiler-common", @@ -1118,7 +1108,7 @@ dependencies = [ [[package]] name = "era-compiler-solidity" version = "1.5.10" -source = "git+https://github.com/matter-labs/era-compiler-solidity?branch=main#8eceeacecd12b7e87c2662a3ba0501b36d05f894" +source = "git+https://github.com/matter-labs/era-compiler-solidity?branch=main#9d8efed4feeab1d2f906b6c2b32635ebb6652c85" dependencies = [ "anyhow", "clap", @@ -1131,10 +1121,8 @@ dependencies = [ "mimalloc", "normpath", "num", - "num_cpus", "path-slash", "rayon", - "rusty_pool", "semver 1.0.23", "serde", "serde_json", @@ -1145,7 +1133,7 @@ dependencies = [ [[package]] name = "era-compiler-vyper" version = "1.5.9" -source = "git+https://github.com/matter-labs/era-compiler-vyper?branch=main#51f8baf7514e2482145d1b2f1e37615fb50bb2ca" +source = "git+https://github.com/matter-labs/era-compiler-vyper?branch=main#9ea0fb7336021d7740a2c0ad851ea4f96b873e12" dependencies = [ "anyhow", "boolinator", @@ -1169,7 +1157,7 @@ dependencies = [ [[package]] name = "era-solc" version = "1.5.10" -source = "git+https://github.com/matter-labs/era-compiler-solidity?branch=main#8eceeacecd12b7e87c2662a3ba0501b36d05f894" +source = "git+https://github.com/matter-labs/era-compiler-solidity?branch=main#9d8efed4feeab1d2f906b6c2b32635ebb6652c85" dependencies = [ "anyhow", "boolinator", @@ -1186,7 +1174,7 @@ dependencies = [ [[package]] name = "era-yul" version = "1.5.10" -source = "git+https://github.com/matter-labs/era-compiler-solidity?branch=main#8eceeacecd12b7e87c2662a3ba0501b36d05f894" +source = "git+https://github.com/matter-labs/era-compiler-solidity?branch=main#9d8efed4feeab1d2f906b6c2b32635ebb6652c85" dependencies = [ "anyhow", "regex", @@ -1248,30 +1236,6 @@ dependencies = [ "uint", ] -[[package]] -name = "evm" -version = "1.0.0-dev" -source = "git+https://github.com/rust-ethereum/evm?rev=f7a23df6c478ca6a151af5f60e62944800529a61#f7a23df6c478ca6a151af5f60e62944800529a61" -dependencies = [ - "evm-interpreter", - "primitive-types", - "sha3 0.10.8", -] - -[[package]] -name = "evm-interpreter" -version = "1.0.0-dev" -source = "git+https://github.com/rust-ethereum/evm?rev=f7a23df6c478ca6a151af5f60e62944800529a61#f7a23df6c478ca6a151af5f60e62944800529a61" -dependencies = [ - "auto_impl", - "parity-scale-codec", - "primitive-types", - "rlp", - "scale-info", - "serde", - "sha3 0.10.8", -] - [[package]] name = "fastrand" version = "2.3.0" @@ -1963,7 +1927,7 @@ dependencies = [ [[package]] name = "inkwell" version = "0.4.0" -source = "git+https://github.com/matter-labs-forks/inkwell?branch=llvm-17#c5d783f52b755f5382e99e3f1179039b9435e3cc" +source = "git+https://github.com/matter-labs-forks/inkwell?branch=llvm-17#b6c1bf7e730d99a8a1e2acf7513befcf80466ba7" dependencies = [ "either", "inkwell_internals", @@ -1972,13 +1936,13 @@ dependencies = [ "once_cell", "parking_lot", "serde", - "thiserror 1.0.64", + "thiserror 2.0.11", ] [[package]] name = "inkwell_internals" version = "0.9.0" -source = "git+https://github.com/matter-labs-forks/inkwell?branch=llvm-17#c5d783f52b755f5382e99e3f1179039b9435e3cc" +source = "git+https://github.com/matter-labs-forks/inkwell?branch=llvm-17#b6c1bf7e730d99a8a1e2acf7513befcf80466ba7" dependencies = [ "proc-macro2", "quote", @@ -2159,7 +2123,7 @@ checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "llvm-sys" version = "170.0.1" -source = "git+https://github.com/matter-labs-forks/llvm-sys.rs?branch=llvm-17.0#b65826dfdb19676637dbddb9f01bcc52ae2c4308" +source = "git+https://github.com/matter-labs-forks/llvm-sys.rs?branch=llvm-17.0#5dad04e81f806046e383ee73a8d1b9ed53161624" dependencies = [ "anyhow", "cc", @@ -2438,9 +2402,9 @@ dependencies = [ [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-src" @@ -3153,9 +3117,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.43" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags 2.8.0", "errno", @@ -3234,49 +3198,12 @@ dependencies = [ "wait-timeout", ] -[[package]] -name = "rusty_pool" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ed36cdb20de66d89a17ea04b8883fc7a386f2cf877aaedca5005583ce4876ff" -dependencies = [ - "crossbeam-channel", - "futures-channel", - "futures-executor", - "num_cpus", -] - [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" -[[package]] -name = "scale-info" -version = "2.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346a3b32eba2640d17a9cb5927056b08f3de90f65b72fe09402c2ad07d684d0b" -dependencies = [ - "bitvec", - "cfg-if", - "derive_more 1.0.0", - "parity-scale-codec", - "scale-info-derive", -] - -[[package]] -name = "scale-info-derive" -version = "2.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6630024bf739e2179b91fb424b28898baf819414262c5d376677dbff1fe7ebf" -dependencies = [ - "proc-macro-crate 3.2.0", - "proc-macro2", - "quote", - "syn 2.0.96", -] - [[package]] name = "schannel" version = "0.1.27" @@ -4006,9 +3933,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" +checksum = "11cd88e12b17c6494200a9c1b683a04fcac9573ed74cd1b62aeb2727c5592243" [[package]] name = "unicode-xid" @@ -4675,7 +4602,7 @@ dependencies = [ [[package]] name = "zksync_vm2" version = "0.2.1" -source = "git+https://github.com/matter-labs/vm2#457d8a7eea9093af9440662e33e598c13ba41633" +source = "git+https://github.com/matter-labs/vm2#70a6e301b12d98db13fd91f67a505441c0defe9a" dependencies = [ "enum_dispatch", "primitive-types", @@ -4687,7 +4614,7 @@ dependencies = [ [[package]] name = "zksync_vm2_interface" version = "0.2.1" -source = "git+https://github.com/matter-labs/vm2#457d8a7eea9093af9440662e33e598c13ba41633" +source = "git+https://github.com/matter-labs/vm2#70a6e301b12d98db13fd91f67a505441c0defe9a" dependencies = [ "primitive-types", ] diff --git a/compiler_tester/Cargo.toml b/compiler_tester/Cargo.toml index 092d386e..31f9c296 100644 --- a/compiler_tester/Cargo.toml +++ b/compiler_tester/Cargo.toml @@ -40,7 +40,6 @@ lazy_static = "=1.5.0" bincode = "=1.3.3" chrono = "=0.4.38" -evm = { git = "https://github.com/rust-ethereum/evm", rev = "f7a23df6c478ca6a151af5f60e62944800529a61" } revm = { git = "https://github.com/bluealloy/revm", rev = "fa5650ee8a4d802f4f3557014dd157adfb074460" } zkevm_opcode_defs = "=0.150.6" diff --git a/compiler_tester/src/compiler_tester/main.rs b/compiler_tester/src/compiler_tester/main.rs index 36e7faec..00a78d37 100644 --- a/compiler_tester/src/compiler_tester/main.rs +++ b/compiler_tester/src/compiler_tester/main.rs @@ -211,7 +211,7 @@ fn main_inner(arguments: Arguments) -> anyhow::Result<()> { ) } compiler_tester::Environment::REVM => { - compiler_tester::EVM::download(executable_download_config_paths)?; + compiler_tester::REVM::download(executable_download_config_paths)?; compiler_tester.run_revm(toolchain) } }?; diff --git a/compiler_tester/src/compilers/eravm/mod.rs b/compiler_tester/src/compilers/eravm/mod.rs index 39745912..508017c7 100644 --- a/compiler_tester/src/compilers/eravm/mod.rs +++ b/compiler_tester/src/compilers/eravm/mod.rs @@ -11,7 +11,7 @@ use era_solc::CollectableError; use crate::compilers::mode::Mode; use crate::compilers::Compiler; use crate::vm::eravm::input::Input as EraVMInput; -use crate::vm::evm::input::Input as EVMInput; +use crate::vm::revm::input::Input as EVMInput; use self::mode::Mode as EraVMMode; diff --git a/compiler_tester/src/compilers/llvm/mod.rs b/compiler_tester/src/compilers/llvm/mod.rs index 55d24a2f..171f4211 100644 --- a/compiler_tester/src/compilers/llvm/mod.rs +++ b/compiler_tester/src/compilers/llvm/mod.rs @@ -11,8 +11,8 @@ use era_solc::CollectableError; use crate::compilers::mode::Mode; use crate::compilers::Compiler; use crate::vm::eravm::input::Input as EraVMInput; -use crate::vm::evm::input::build::Build as EVMBuild; -use crate::vm::evm::input::Input as EVMInput; +use crate::vm::revm::input::build::Build as EVMBuild; +use crate::vm::revm::input::Input as EVMInput; use self::mode::Mode as LLVMMode; @@ -116,7 +116,6 @@ impl Compiler for LLVMCompiler { era_compiler_common::HashType::Ipfs, mode.llvm_optimizer_settings.to_owned(), llvm_options, - None, debug_config.clone(), )?; build.check_errors()?; diff --git a/compiler_tester/src/compilers/mod.rs b/compiler_tester/src/compilers/mod.rs index 08566f4f..8501b829 100644 --- a/compiler_tester/src/compilers/mod.rs +++ b/compiler_tester/src/compilers/mod.rs @@ -11,7 +11,7 @@ pub mod vyper; pub mod yul; use crate::vm::eravm::input::Input as EraVMInput; -use crate::vm::evm::input::Input as EVMInput; +use crate::vm::revm::input::Input as EVMInput; use self::mode::Mode; diff --git a/compiler_tester/src/compilers/solidity/mod.rs b/compiler_tester/src/compilers/solidity/mod.rs index 6db0b4a9..80e9c4bc 100644 --- a/compiler_tester/src/compilers/solidity/mod.rs +++ b/compiler_tester/src/compilers/solidity/mod.rs @@ -19,8 +19,8 @@ use crate::compilers::cache::Cache; use crate::compilers::mode::Mode; use crate::compilers::Compiler; use crate::vm::eravm::input::Input as EraVMInput; -use crate::vm::evm::input::build::Build as EVMBuild; -use crate::vm::evm::input::Input as EVMInput; +use crate::vm::revm::input::build::Build as EVMBuild; +use crate::vm::revm::input::Input as EVMInput; use self::cache_key::CacheKey; use self::mode::Mode as SolidityMode; @@ -426,6 +426,8 @@ impl Compiler for SolidityCompiler { let solc_compiler = SolidityCompiler::executable(&mode.solc_version)?; + let linker_symbols = libraries.as_linker_symbols()?; + let project = era_compiler_solidity::Project::try_from_solc_output( libraries, mode.solc_codegen, @@ -439,10 +441,11 @@ impl Compiler for SolidityCompiler { era_compiler_common::HashType::Ipfs, mode.llvm_optimizer_settings.to_owned(), llvm_options, - None, debug_config, )?; build.check_errors()?; + let build = build.link(linker_symbols); + build.check_errors()?; let builds: HashMap = build .results .into_iter() diff --git a/compiler_tester/src/compilers/solidity/upstream/mod.rs b/compiler_tester/src/compilers/solidity/upstream/mod.rs index cf1ae610..50d2e6df 100644 --- a/compiler_tester/src/compilers/solidity/upstream/mod.rs +++ b/compiler_tester/src/compilers/solidity/upstream/mod.rs @@ -16,8 +16,8 @@ use crate::compilers::yul::mode_upstream::Mode as YulUpstreamMode; use crate::compilers::Compiler; use crate::toolchain::Toolchain; use crate::vm::eravm::input::Input as EraVMInput; -use crate::vm::evm::input::build::Build as EVMBuild; -use crate::vm::evm::input::Input as EVMInput; +use crate::vm::revm::input::build::Build as EVMBuild; +use crate::vm::revm::input::Input as EVMInput; use self::mode::Mode as SolidityUpstreamMode; use self::solc::standard_json::input::language::Language as SolcStandardJsonInputLanguage; diff --git a/compiler_tester/src/compilers/vyper/mod.rs b/compiler_tester/src/compilers/vyper/mod.rs index 907d6505..e7a72051 100644 --- a/compiler_tester/src/compilers/vyper/mod.rs +++ b/compiler_tester/src/compilers/vyper/mod.rs @@ -16,6 +16,7 @@ use crate::compilers::cache::Cache; use crate::compilers::mode::Mode; use crate::compilers::Compiler; use crate::vm::eravm::input::Input as EraVMInput; +use crate::vm::revm::input::Input as EVMInput; use self::cache_key::CacheKey; use self::mode::Mode as VyperMode; @@ -267,7 +268,7 @@ impl Compiler for VyperCompiler { _test_params: Option<&solidity_adapter::Params>, _llvm_options: Vec, _debug_config: Option, - ) -> anyhow::Result { + ) -> anyhow::Result { todo!() } diff --git a/compiler_tester/src/compilers/yul/mod.rs b/compiler_tester/src/compilers/yul/mod.rs index 133f710a..cda374d4 100644 --- a/compiler_tester/src/compilers/yul/mod.rs +++ b/compiler_tester/src/compilers/yul/mod.rs @@ -16,8 +16,8 @@ use crate::compilers::solidity::SolidityCompiler; use crate::compilers::Compiler; use crate::toolchain::Toolchain; use crate::vm::eravm::input::Input as EraVMInput; -use crate::vm::evm::input::build::Build as EVMBuild; -use crate::vm::evm::input::Input as EVMInput; +use crate::vm::revm::input::build::Build as EVMBuild; +use crate::vm::revm::input::Input as EVMInput; use self::mode::Mode as YulMode; diff --git a/compiler_tester/src/directories/ethereum/test.rs b/compiler_tester/src/directories/ethereum/test.rs index 1f2f7742..3c679990 100644 --- a/compiler_tester/src/directories/ethereum/test.rs +++ b/compiler_tester/src/directories/ethereum/test.rs @@ -19,7 +19,7 @@ use crate::test::selector::TestSelector; use crate::test::Test; use crate::vm::address_iterator::AddressIterator; use crate::vm::eravm::address_iterator::EraVMAddressIterator; -use crate::vm::evm::address_iterator::EVMAddressIterator; +use crate::vm::revm::address_iterator::EVMAddressIterator; /// /// The Ethereum compiler test. diff --git a/compiler_tester/src/directories/matter_labs/test/metadata/case/mod.rs b/compiler_tester/src/directories/matter_labs/test/metadata/case/mod.rs index a7e54efb..24cff2d5 100644 --- a/compiler_tester/src/directories/matter_labs/test/metadata/case/mod.rs +++ b/compiler_tester/src/directories/matter_labs/test/metadata/case/mod.rs @@ -14,7 +14,7 @@ use crate::environment::Environment; use crate::test::instance::Instance; use crate::vm::address_iterator::AddressIterator; use crate::vm::eravm::address_iterator::EraVMAddressIterator; -use crate::vm::evm::address_iterator::EVMAddressIterator; +use crate::vm::revm::address_iterator::EVMAddressIterator; use self::input::expected::Expected; use self::input::Input; diff --git a/compiler_tester/src/directories/matter_labs/test/mod.rs b/compiler_tester/src/directories/matter_labs/test/mod.rs index 184d2fca..fbfee307 100644 --- a/compiler_tester/src/directories/matter_labs/test/mod.rs +++ b/compiler_tester/src/directories/matter_labs/test/mod.rs @@ -25,7 +25,7 @@ use crate::test::selector::TestSelector; use crate::test::Test; use crate::vm::address_iterator::AddressIterator; use crate::vm::eravm::address_iterator::EraVMAddressIterator; -use crate::vm::evm::address_iterator::EVMAddressIterator; +use crate::vm::revm::address_iterator::EVMAddressIterator; use self::metadata::case::input::calldata::Calldata as MatterLabsCaseInputCalldata; use self::metadata::case::input::expected::Expected as MatterLabsCaseInputExpected; diff --git a/compiler_tester/src/lib.rs b/compiler_tester/src/lib.rs index caca803a..c9c78f76 100644 --- a/compiler_tester/src/lib.rs +++ b/compiler_tester/src/lib.rs @@ -50,7 +50,7 @@ pub use crate::vm::eravm::deployers::dummy_deployer::DummyDeployer as EraVMNativ pub use crate::vm::eravm::deployers::system_contract_deployer::SystemContractDeployer as EraVMSystemContractDeployer; pub use crate::vm::eravm::deployers::EraVMDeployer; pub use crate::vm::eravm::EraVM; -pub use crate::vm::evm::EVM; +pub use crate::vm::revm::REVM; pub use crate::workflow::Workflow; /// The debug directory path. @@ -156,38 +156,6 @@ impl CompilerTester { Ok(()) } - /// - /// Runs all tests on EVM emulator. - /// - pub fn run_evm(self, toolchain: Toolchain) -> anyhow::Result<()> { - let tests = self.all_tests(era_compiler_common::Target::EVM, toolchain)?; - - let _: Vec<()> = tests - .into_par_iter() - .map(|(test, compiler, mode)| { - let mode_string = mode.to_string(); - let specialized_debug_config = self - .debug_config - .as_ref() - .and_then(|config| config.create_subdirectory(mode_string.as_str()).ok()); - if let Some(test) = test.build_for_evm( - mode, - compiler, - Environment::REVM, - self.summary.clone(), - &self.filters, - specialized_debug_config, - ) { - if let Workflow::BuildAndRun = self.workflow { - test.run_evm_emulator(self.summary.clone()) - }; - } - }) - .collect(); - - Ok(()) - } - /// /// Runs all tests on REVM. /// diff --git a/compiler_tester/src/test/case/input/balance.rs b/compiler_tester/src/test/case/input/balance.rs index db6ad675..c065430f 100644 --- a/compiler_tester/src/test/case/input/balance.rs +++ b/compiler_tester/src/test/case/input/balance.rs @@ -11,9 +11,8 @@ use crate::test::context::input::InputContext; use crate::test::description::TestDescription; use crate::vm::eravm::system_context::SystemContext; use crate::vm::eravm::EraVM; -use crate::vm::evm::EVM; use crate::vm::revm::revm_type_conversions::web3_address_to_revm_address; -use crate::vm::revm::Revm; +use crate::vm::revm::REVM; /// /// The balance check input variant. @@ -74,22 +73,10 @@ impl Balance { } } - /// - /// Runs the balance check on EVM emulator. - /// - pub fn run_evm_emulator( - self, - _summary: Arc>, - _vm: &EVM, - _context: InputContext<'_>, - ) { - todo!() - } - /// /// Runs the balance check on REVM. /// - pub fn run_revm(self, summary: Arc>, vm: &mut Revm, context: InputContext<'_>) { + pub fn run_revm(self, summary: Arc>, vm: &mut REVM, context: InputContext<'_>) { let input_index = context.selector; let test = TestDescription::from_context(context, InputIdentifier::Balance { input_index }); let found = vm diff --git a/compiler_tester/src/test/case/input/deploy_evm.rs b/compiler_tester/src/test/case/input/deploy_evm.rs index ebb9fdf6..28756954 100644 --- a/compiler_tester/src/test/case/input/deploy_evm.rs +++ b/compiler_tester/src/test/case/input/deploy_evm.rs @@ -18,11 +18,10 @@ use crate::test::description::TestDescription; use crate::test::InputContext; use crate::vm::eravm::deployers::EraVMDeployer; use crate::vm::eravm::EraVM; -use crate::vm::evm::EVM; use crate::vm::revm::revm_type_conversions::revm_bytes_to_vec_value; use crate::vm::revm::revm_type_conversions::transform_success_output; -use crate::vm::revm::Revm; +use crate::vm::revm::REVM; /// /// The EVM deploy contract call input variant. @@ -71,60 +70,16 @@ impl DeployEVM { } impl DeployEVM { - /// - /// Runs the deploy transaction on EVM emulator. - /// - pub fn run_evm_emulator( - self, - summary: Arc>, - vm: &mut EVM, - context: InputContext<'_>, - ) { - let test = TestDescription::from_context( - context, - InputIdentifier::Deployer { - contract_identifier: self.identifier.clone(), - }, - ); - let name = test.selector.to_string(); - - vm.populate_storage(self.storage.inner); - let result = match vm.execute_deploy_code( - name, - self.identifier.as_str(), - self.caller, - self.value, - self.calldata.inner.clone(), - ) { - Ok(execution_result) => execution_result, - Err(error) => { - Summary::invalid(summary, test, error); - return; - } - }; - if result.output == self.expected { - Summary::passed_runtime(summary, test, result.cycles, 0, result.gas); - } else { - Summary::failed( - summary, - test, - self.expected, - result.output, - self.calldata.inner, - ); - } - } - /// /// Runs the deploy transaction on native REVM. /// pub fn run_revm<'b>( self, summary: Arc>, - vm: Revm<'b>, + vm: REVM<'b>, evm_version: Option, context: InputContext<'_>, - ) -> Revm<'b> { + ) -> REVM<'b> { let test = TestDescription::from_context( context, InputIdentifier::Deployer { diff --git a/compiler_tester/src/test/case/input/mod.rs b/compiler_tester/src/test/case/input/mod.rs index 663420a0..e15251ff 100644 --- a/compiler_tester/src/test/case/input/mod.rs +++ b/compiler_tester/src/test/case/input/mod.rs @@ -25,8 +25,7 @@ use crate::test::instance::Instance; use crate::test::InputContext; use crate::vm::eravm::deployers::EraVMDeployer; use crate::vm::eravm::EraVM; -use crate::vm::evm::EVM; -use crate::vm::revm::Revm; +use crate::vm::revm::REVM; use self::balance::Balance; use self::calldata::Calldata; @@ -385,36 +384,16 @@ impl Input { }; } - /// - /// Runs the input on EVM emulator. - /// - pub fn run_evm_emulator( - self, - summary: Arc>, - vm: &mut EVM, - context: InputContext<'_>, - ) { - match self { - Self::DeployEraVM { .. } => panic!("EraVM deploy transaction cannot be run on EVM"), - Self::DeployEVM(deploy) => deploy.run_evm_emulator(summary, vm, context), - Self::Runtime(runtime) => runtime.run_evm_emulator(summary, vm, context), - Self::StorageEmpty(storage_empty) => { - storage_empty.run_evm_emulator(summary, vm, context) - } - Self::Balance(balance_check) => balance_check.run_evm_emulator(summary, vm, context), - }; - } - /// /// Runs the input on REVM. /// pub fn run_revm<'b>( self, summary: Arc>, - mut vm: Revm<'b>, + mut vm: REVM<'b>, evm_version: Option, context: InputContext<'_>, - ) -> Revm<'b> { + ) -> REVM<'b> { match self { Self::DeployEraVM { .. } => panic!("EraVM deploy transaction cannot be run on REVM"), Self::DeployEVM(deploy) => deploy.run_revm(summary, vm, evm_version, context), diff --git a/compiler_tester/src/test/case/input/output/event.rs b/compiler_tester/src/test/case/input/output/event.rs index 92812b63..2f3447c3 100644 --- a/compiler_tester/src/test/case/input/output/event.rs +++ b/compiler_tester/src/test/case/input/output/event.rs @@ -163,39 +163,6 @@ impl From for Event { } } -impl From for Event { - fn from(log: evm::Log) -> Self { - let _address = log.address; - let topics = log - .topics - .into_iter() - .map(|topic| Value::Certain(crate::utils::h256_to_u256(&topic))) - .collect(); - let values: Vec = log - .data - .chunks(era_compiler_common::BYTE_LENGTH_FIELD) - .map(|word| { - let value = if word.len() != era_compiler_common::BYTE_LENGTH_FIELD { - let mut word_padded = word.to_vec(); - word_padded.extend(vec![ - 0u8; - era_compiler_common::BYTE_LENGTH_FIELD - word.len() - ]); - web3::types::U256::from_big_endian(word_padded.as_slice()) - } else { - web3::types::U256::from_big_endian(word) - }; - Value::Certain(value) - }) - .collect(); - Self { - address: Some(log.address), - topics, - values, - } - } -} - impl PartialEq for Event { fn eq(&self, other: &Self) -> bool { if let (Some(address1), Some(address2)) = (self.address, other.address) { diff --git a/compiler_tester/src/test/case/input/output/mod.rs b/compiler_tester/src/test/case/input/output/mod.rs index 0769b3b6..d2a5229e 100644 --- a/compiler_tester/src/test/case/input/output/mod.rs +++ b/compiler_tester/src/test/case/input/output/mod.rs @@ -12,7 +12,6 @@ use crate::directories::matter_labs::test::metadata::case::input::expected::vari use crate::directories::matter_labs::test::metadata::case::input::expected::Expected as MatterLabsTestExpected; use crate::test::case::input::value::Value; use crate::test::instance::Instance; -use crate::vm::evm::output::Output as EVMOutput; use self::event::Event; @@ -243,36 +242,6 @@ impl From for Output { } } -impl From for Output { - fn from(output: EVMOutput) -> Self { - let return_data = output - .return_data - .chunks(era_compiler_common::BYTE_LENGTH_FIELD) - .map(|word| { - let value = if word.len() != era_compiler_common::BYTE_LENGTH_FIELD { - let mut word_padded = word.to_vec(); - word_padded.extend(vec![ - 0u8; - era_compiler_common::BYTE_LENGTH_FIELD - word.len() - ]); - web3::types::U256::from_big_endian(word_padded.as_slice()) - } else { - web3::types::U256::from_big_endian(word) - }; - Value::Certain(value) - }) - .collect(); - - let events = output.logs.into_iter().map(Event::from).collect(); - - Self { - return_data, - exception: output.exception, - events, - } - } -} - impl PartialEq for Output { fn eq(&self, other: &Self) -> bool { if self.exception != other.exception { diff --git a/compiler_tester/src/test/case/input/runtime.rs b/compiler_tester/src/test/case/input/runtime.rs index f6f5cbc5..305f6155 100644 --- a/compiler_tester/src/test/case/input/runtime.rs +++ b/compiler_tester/src/test/case/input/runtime.rs @@ -19,11 +19,10 @@ use crate::test::context::input::InputContext; use crate::test::description::TestDescription; use crate::vm::eravm::system_context::SystemContext; use crate::vm::eravm::EraVM; -use crate::vm::evm::EVM; use crate::vm::revm::revm_type_conversions::revm_bytes_to_vec_value; use crate::vm::revm::revm_type_conversions::transform_success_output; -use crate::vm::revm::Revm; +use crate::vm::revm::REVM; /// /// The contract call input variant. @@ -130,58 +129,16 @@ impl Runtime { } } - /// - /// Runs the call on EVM emulator. - /// - pub fn run_evm_emulator( - self, - summary: Arc>, - vm: &mut EVM, - context: InputContext<'_>, - ) { - let input_index = context.selector; - let test = TestDescription::from_context( - context, - Self::select_input_identifier(self.name, input_index), - ); - let name = test.selector.to_string(); - vm.populate_storage(self.storage.inner); - let result = match vm.execute_runtime_code( - name, - self.address, - self.caller, - self.value, - self.calldata.inner.clone(), - ) { - Ok(execution_result) => execution_result, - Err(error) => { - Summary::invalid(summary, test, error); - return; - } - }; - if result.output == self.expected { - Summary::passed_runtime(summary, test, result.cycles, result.ergs, result.gas); - } else { - Summary::failed( - summary, - test, - self.expected, - result.output, - self.calldata.inner, - ); - } - } - /// /// Runs the call on REVM. /// pub fn run_revm<'b>( self, summary: Arc>, - vm: Revm<'b>, + vm: REVM<'b>, evm_version: Option, context: InputContext<'_>, - ) -> Revm<'b> { + ) -> REVM<'b> { let input_index = context.selector; let test = TestDescription::from_context( context, diff --git a/compiler_tester/src/test/case/input/storage_empty.rs b/compiler_tester/src/test/case/input/storage_empty.rs index dce8342f..8414085d 100644 --- a/compiler_tester/src/test/case/input/storage_empty.rs +++ b/compiler_tester/src/test/case/input/storage_empty.rs @@ -10,8 +10,7 @@ use crate::test::case::input::identifier::InputIdentifier; use crate::test::description::TestDescription; use crate::test::InputContext; use crate::vm::eravm::EraVM; -use crate::vm::evm::EVM; -use crate::vm::revm::Revm; +use crate::vm::revm::REVM; /// /// The storage emptiness check input variant. @@ -47,22 +46,10 @@ impl StorageEmpty { } } - /// - /// Runs the storage empty check on EVM emulator. - /// - pub fn run_evm_emulator( - self, - _summary: Arc>, - _vm: &EVM, - _context: InputContext<'_>, - ) { - todo!() - } - /// /// Runs the storage empty check on REVM. /// - pub fn run_revm(self, summary: Arc>, vm: &mut Revm, context: InputContext<'_>) { + pub fn run_revm(self, summary: Arc>, vm: &mut REVM, context: InputContext<'_>) { let input_index = context.selector; let test = TestDescription::from_context(context, InputIdentifier::StorageEmpty { input_index }); diff --git a/compiler_tester/src/test/case/mod.rs b/compiler_tester/src/test/case/mod.rs index ba7803d7..265f7086 100644 --- a/compiler_tester/src/test/case/mod.rs +++ b/compiler_tester/src/test/case/mod.rs @@ -14,8 +14,7 @@ use crate::summary::Summary; use crate::test::instance::Instance; use crate::vm::eravm::deployers::EraVMDeployer; use crate::vm::eravm::EraVM; -use crate::vm::evm::EVM; -use crate::vm::revm::Revm; +use crate::vm::revm::REVM; use self::input::Input; @@ -117,25 +116,6 @@ impl Case { } } - /// - /// Runs the case on EVM emulator. - /// - pub fn run_evm_emulator( - self, - summary: Arc>, - mut vm: EVM, - context: &CaseContext, - ) { - for (index, input) in self.inputs.into_iter().enumerate() { - let context = InputContext { - case_context: context, - case_name: &self.name, - selector: index, - }; - input.run_evm_emulator(summary.clone(), &mut vm, context) - } - } - /// /// Runs the case on REVM. /// @@ -145,7 +125,7 @@ impl Case { evm_version: Option, context: &CaseContext, ) { - let mut vm = Revm::new(); + let mut vm = REVM::new(); for (index, input) in self.inputs.into_iter().enumerate() { let context = InputContext { case_context: context, diff --git a/compiler_tester/src/test/mod.rs b/compiler_tester/src/test/mod.rs index 06430046..5d840bf4 100644 --- a/compiler_tester/src/test/mod.rs +++ b/compiler_tester/src/test/mod.rs @@ -8,11 +8,12 @@ pub mod description; pub mod instance; pub mod selector; -use solidity_adapter::EVMVersion; use std::collections::HashMap; use std::sync::Arc; use std::sync::Mutex; +use solidity_adapter::EVMVersion; + use crate::compilers::mode::Mode; use crate::summary::Summary; use crate::test::case::Case; @@ -20,10 +21,7 @@ use crate::test::context::case::CaseContext; use crate::test::context::input::InputContext; use crate::vm::eravm::deployers::EraVMDeployer; use crate::vm::eravm::EraVM; -use crate::vm::evm::input::build::Build as EVMBuild; -use crate::vm::evm::invoker::Invoker as EVMInvoker; -use crate::vm::evm::runtime::Runtime as EVMRuntime; -use crate::vm::evm::EVM; +use crate::vm::revm::input::build::Build as EVMBuild; /// /// The test. @@ -88,29 +86,6 @@ impl Test { } } - /// - /// Runs the test on EVM emulator. - /// - pub fn run_evm_emulator(self, summary: Arc>) { - for case in self.cases { - let config = evm::standard::Config::shanghai(); - let etable = - evm::Etable::::runtime( - ); - let resolver = evm::standard::EtableResolver::new(&config, &(), &etable); - let invoker = EVMInvoker::new(&config, &resolver); - - let vm = EVM::new(self.evm_builds.clone(), invoker); - - let context = CaseContext { - name: &self.name, - mode: &self.mode, - group: &self.group, - }; - case.run_evm_emulator(summary.clone(), vm, &context); - } - } - /// /// Runs the test on REVM. /// diff --git a/compiler_tester/src/utils/mod.rs b/compiler_tester/src/utils/mod.rs index 23b0d796..0714db50 100644 --- a/compiler_tester/src/utils/mod.rs +++ b/compiler_tester/src/utils/mod.rs @@ -2,6 +2,8 @@ //! The compiler tester utils. //! +#![allow(dead_code)] + pub mod timer; use sha3::Digest; diff --git a/compiler_tester/src/vm/evm/invoker.rs b/compiler_tester/src/vm/evm/invoker.rs deleted file mode 100644 index 03578662..00000000 --- a/compiler_tester/src/vm/evm/invoker.rs +++ /dev/null @@ -1,21 +0,0 @@ -//! -//! The EVM invoker. -//! - -use crate::vm::evm::runtime::Runtime as EVMRuntime; - -/// -/// The EVM resolver type. -/// -pub type Resolver<'evm> = evm::standard::EtableResolver< - 'evm, - 'evm, - 'evm, - (), - evm::Etable, EVMRuntime, evm::trap::CallCreateTrap>, ->; - -/// -/// The EVM wrapped invoker type. -/// -pub type Invoker<'evm> = evm::standard::Invoker<'evm, 'evm, Resolver<'evm>>; diff --git a/compiler_tester/src/vm/evm/mod.rs b/compiler_tester/src/vm/evm/mod.rs deleted file mode 100644 index 162cda66..00000000 --- a/compiler_tester/src/vm/evm/mod.rs +++ /dev/null @@ -1,212 +0,0 @@ -//! -//! The EVM emulator. -//! - -pub mod address_iterator; -pub mod input; -pub mod invoker; -pub mod output; -pub mod runtime; - -use std::collections::HashMap; -use std::path::PathBuf; -use std::time::Duration; -use std::time::Instant; - -use colored::Colorize; - -use crate::vm::execution_result::ExecutionResult; - -use self::input::build::Build as EVMBuild; -use self::invoker::Invoker as EVMInvoker; -use self::output::Output as EVMOutput; -use self::runtime::Runtime as EVMRuntime; - -/// -/// The EVM emulator. -/// -pub struct EVM<'evm> { - /// The EVM runtime. - runtime: EVMRuntime, - /// The builds to deploy. - builds: HashMap, - /// The EVM invoker. - invoker: EVMInvoker<'evm>, -} - -impl<'evm> EVM<'evm> { - /// - /// A shortcut constructor. - /// - pub fn new(builds: HashMap, invoker: EVMInvoker<'evm>) -> Self { - let runtime = EVMRuntime::default(); - - Self { - runtime, - builds, - invoker, - } - } - - /// - /// Downloads the necessary compiler executables. - /// - pub fn download(executable_download_config_paths: Vec) -> anyhow::Result<()> { - let mut http_client_builder = reqwest::blocking::ClientBuilder::new(); - http_client_builder = http_client_builder.connect_timeout(Duration::from_secs(60)); - http_client_builder = http_client_builder.pool_idle_timeout(Duration::from_secs(60)); - http_client_builder = http_client_builder.timeout(Duration::from_secs(60)); - let http_client = http_client_builder.build()?; - - let download_time_start = Instant::now(); - println!( - " {} compiler executables", - "Downloading".bright_green().bold() - ); - for config_path in executable_download_config_paths.into_iter() { - era_compiler_downloader::Downloader::new(http_client.clone()) - .download(config_path.as_path())?; - } - println!( - " {} downloading compiler executables in {}m{:02}s", - "Finished".bright_green().bold(), - download_time_start.elapsed().as_secs() / 60, - download_time_start.elapsed().as_secs() % 60, - ); - - Ok(()) - } - - /// - /// Runs a deploy code test transaction. - /// - pub fn execute_deploy_code( - &mut self, - _test_name: String, - path: &str, - caller: web3::types::Address, - value: Option, - constructor_args: Vec, - ) -> anyhow::Result { - let build = self.builds.get(path).expect("Always valid"); - let mut deploy_code = build.deploy_build.to_owned(); - deploy_code.extend(constructor_args); - - self.runtime - .balances - .insert(caller, web3::types::U256::max_value()); - - let (address, exception) = match evm::transact( - evm::standard::TransactArgs::Create { - caller, - value: value.unwrap_or_default().into(), - init_code: deploy_code, - salt: None, - gas_limit: web3::types::U256::from_str_radix( - "ffffffff", - era_compiler_common::BASE_HEXADECIMAL, - ) - .expect("Always valid"), - gas_price: web3::types::U256::from_str_radix( - "b2d05e00", - era_compiler_common::BASE_HEXADECIMAL, - ) - .expect("Always valid"), - access_list: vec![], - }, - None, - &mut self.runtime, - &self.invoker, - ) { - Ok(evm::standard::TransactValue::Create { succeed, address }) => match succeed { - evm::ExitSucceed::Returned => (address, false), - _ => (web3::types::Address::zero(), true), - }, - Ok(evm::standard::TransactValue::Call { .. }) => { - unreachable!("The `Create` transaction must be executed above") - } - Err(_error) => (web3::types::Address::zero(), true), - }; - - let mut return_data = vec![ - 0u8; - era_compiler_common::BYTE_LENGTH_FIELD - - era_compiler_common::BYTE_LENGTH_ETH_ADDRESS - ]; - return_data.extend(address.as_fixed_bytes()); - let events = self.runtime.logs.drain(..).collect(); - let output = EVMOutput::new(return_data, exception, events); - - let execution_result = ExecutionResult::from(output); - Ok(execution_result) - } - - /// - /// Runs a runtime code transaction. - /// - pub fn execute_runtime_code( - &mut self, - _test_name: String, - address: web3::types::Address, - caller: web3::types::Address, - value: Option, - calldata: Vec, - ) -> anyhow::Result { - self.runtime - .balances - .insert(caller, web3::types::U256::max_value()); // TODO - - let (return_data, exception) = match evm::transact( - evm::standard::TransactArgs::Call { - caller, - address, - value: value.unwrap_or_default().into(), - data: calldata, - gas_limit: web3::types::U256::from_str_radix( - "ffffffff", - era_compiler_common::BASE_HEXADECIMAL, - ) - .expect("Always valid"), - gas_price: web3::types::U256::from_str_radix( - "b2d05e00", - era_compiler_common::BASE_HEXADECIMAL, - ) - .expect("Always valid"), - access_list: vec![], - }, - None, - &mut self.runtime, - &self.invoker, - ) { - Ok(evm::standard::TransactValue::Call { succeed, retval }) => { - (retval, succeed != evm::ExitSucceed::Returned) - } - Ok(evm::standard::TransactValue::Create { .. }) => { - unreachable!("The `Call` transaction must be executed above") - } - Err(_error) => (vec![], true), - }; - - let events = self.runtime.logs.drain(..).collect(); - let output = EVMOutput::new(return_data, exception, events); - - let execution_result = ExecutionResult::from(output); - Ok(execution_result) - } - - /// - /// Adds values to storage. - /// - pub fn populate_storage( - &mut self, - values: HashMap<(web3::types::Address, web3::types::U256), web3::types::H256>, - ) { - for ((address, key), value) in values.into_iter() { - self.runtime - .storages - .entry(address) - .or_default() - .insert(crate::utils::u256_to_h256(&key), value); - } - } -} diff --git a/compiler_tester/src/vm/evm/output.rs b/compiler_tester/src/vm/evm/output.rs deleted file mode 100644 index 042718f4..00000000 --- a/compiler_tester/src/vm/evm/output.rs +++ /dev/null @@ -1,28 +0,0 @@ -//! -//! The EVM output. -//! - -/// -/// The EVM output. -/// -pub struct Output { - /// The return data. - pub return_data: Vec, - /// The exception flag. - pub exception: bool, - /// The emitted logs. - pub logs: Vec, -} - -impl Output { - /// - /// A shortcut constructor. - /// - pub fn new(return_data: Vec, exception: bool, logs: Vec) -> Self { - Self { - return_data, - exception, - logs, - } - } -} diff --git a/compiler_tester/src/vm/evm/runtime.rs b/compiler_tester/src/vm/evm/runtime.rs deleted file mode 100644 index c649569f..00000000 --- a/compiler_tester/src/vm/evm/runtime.rs +++ /dev/null @@ -1,242 +0,0 @@ -//! -//! The EVM runtime. -//! - -use std::collections::HashMap; - -/// -/// The EVM runtime. -/// -#[derive(Debug, Default)] -pub struct Runtime { - /// The contract codes. - pub codes: HashMap>, - /// The contract balances. - pub balances: HashMap, - /// The contract nonces. - pub nonces: HashMap, - /// The contract storages. - pub storages: HashMap>, - /// The contract logs. - pub logs: Vec, -} - -impl Runtime { - /// - /// A shortcut constructor. - /// - pub fn new( - codes: HashMap>, - balances: HashMap, - nonces: HashMap, - storages: HashMap>, - logs: Vec, - ) -> Self { - Self { - codes, - balances, - nonces, - storages, - logs, - } - } -} - -impl evm::RuntimeEnvironment for Runtime { - fn block_hash(&self, _number: web3::types::U256) -> web3::types::H256 { - crate::utils::u256_to_h256( - &web3::types::U256::from_str_radix( - "3737373737373737373737373737373737373737373737373737373737373862", - era_compiler_common::BASE_HEXADECIMAL, - ) - .expect("Always valid"), - ) - } - - fn block_number(&self) -> web3::types::U256 { - web3::types::U256::from_str_radix("12c", era_compiler_common::BASE_HEXADECIMAL) - .expect("Always valid") - } - - fn block_coinbase(&self) -> web3::types::H160 { - crate::utils::u256_to_address( - &web3::types::U256::from_str_radix("8001", era_compiler_common::BASE_HEXADECIMAL) - .expect("Always valid"), - ) - } - - fn block_timestamp(&self) -> web3::types::U256 { - web3::types::U256::from_str_radix("deadbeef", era_compiler_common::BASE_HEXADECIMAL) - .expect("Always valid") - } - - fn block_difficulty(&self) -> web3::types::U256 { - web3::types::U256::from_str_radix("8e1bc9bf04000", era_compiler_common::BASE_HEXADECIMAL) - .expect("Always valid") - } - - fn block_randomness(&self) -> Option { - None - } - - fn block_gas_limit(&self) -> web3::types::U256 { - web3::types::U256::from_str_radix("40000000", era_compiler_common::BASE_HEXADECIMAL) - .expect("Always valid") - } - - fn block_base_fee_per_gas(&self) -> web3::types::U256 { - web3::types::U256::from_dec_str("7").expect("Always valid") - } - - fn chain_id(&self) -> web3::types::U256 { - web3::types::U256::from_dec_str("280").expect("Always valid") - } -} - -impl evm::RuntimeBaseBackend for Runtime { - fn balance(&self, address: web3::types::H160) -> web3::types::U256 { - self.balances - .get(&address) - .cloned() - .unwrap_or(web3::types::U256::zero()) - } - - fn code_size(&self, address: web3::types::H160) -> web3::types::U256 { - self.codes - .get(&address) - .map(|code| web3::types::U256::from(code.len())) - .unwrap_or(web3::types::U256::zero()) - } - - fn code_hash(&self, _address: web3::types::H160) -> web3::types::H256 { - web3::types::H256::zero() - } - - fn code(&self, address: web3::types::H160) -> Vec { - self.codes.get(&address).cloned().unwrap_or_default() - } - - fn storage(&self, address: web3::types::H160, index: web3::types::H256) -> web3::types::H256 { - self.storages - .get(&address) - .and_then(|storage| storage.get(&index)) - .cloned() - .unwrap_or_default() - } - - fn exists(&self, address: web3::types::H160) -> bool { - self.codes.contains_key(&address) - } - - fn nonce(&self, address: web3::types::H160) -> web3::types::U256 { - self.nonces.get(&address).copied().unwrap_or_default() - } -} - -impl evm::RuntimeBackend for Runtime { - fn original_storage( - &self, - address: web3::types::H160, - index: web3::types::H256, - ) -> web3::types::H256 { - evm::RuntimeBaseBackend::storage(self, address, index) - } - - fn deleted(&self, _address: web3::types::H160) -> bool { - false - } - - fn is_cold(&self, _address: web3::types::H160, _index: Option) -> bool { - false - } - - fn is_hot(&self, address: web3::types::H160, index: Option) -> bool { - !self.is_cold(address, index) - } - - fn mark_hot(&mut self, _address: web3::types::H160, _index: Option) {} - - fn set_storage( - &mut self, - address: web3::types::H160, - index: web3::types::H256, - value: web3::types::H256, - ) -> Result<(), evm::ExitError> { - self.storages - .entry(address) - .and_modify(|storage| { - storage.insert(index, value); - }) - .or_insert_with(|| { - let mut storage = HashMap::new(); - storage.insert(index, value); - storage - }); - Ok(()) - } - - fn log(&mut self, log: evm::Log) -> Result<(), evm::ExitError> { - self.logs.push(log); - Ok(()) - } - - fn mark_delete(&mut self, _address: web3::types::H160) {} - - fn reset_storage(&mut self, _address: web3::types::H160) {} - - fn set_code( - &mut self, - address: web3::types::H160, - code: Vec, - ) -> Result<(), evm::ExitError> { - self.codes.insert(address, code); - Ok(()) - } - - fn reset_balance(&mut self, address: web3::types::H160) { - self.balances.insert(address, web3::types::U256::zero()); - } - - fn deposit(&mut self, target: web3::types::H160, value: web3::types::U256) { - self.balances - .entry(target) - .and_modify(|balance| *balance += value) - .or_insert(value); - } - - fn withdrawal( - &mut self, - source: web3::types::H160, - value: web3::types::U256, - ) -> Result<(), evm::ExitError> { - let balance = self - .balances - .get_mut(&source) - .ok_or(evm::ExitError::Exception(evm::ExitException::OutOfFund))?; - if *balance < value { - return Err(evm::ExitError::Exception(evm::ExitException::OutOfFund)); - } - *balance -= value; - Ok(()) - } - - fn transfer(&mut self, transfer: evm::Transfer) -> Result<(), evm::ExitError> { - self.withdrawal(transfer.source, transfer.value)?; - self.deposit(transfer.target, transfer.value); - Ok(()) - } - - fn inc_nonce(&mut self, address: web3::types::H160) -> Result<(), evm::ExitError> { - *self - .nonces - .entry(address) - .or_insert_with(web3::types::U256::zero) += web3::types::U256::one(); - Ok(()) - } -} - -impl evm::TransactionalBackend for Runtime { - fn push_substate(&mut self) {} - - fn pop_substate(&mut self, _strategy: evm::MergeStrategy) {} -} diff --git a/compiler_tester/src/vm/execution_result.rs b/compiler_tester/src/vm/execution_result.rs index 7598b445..ad44ac65 100644 --- a/compiler_tester/src/vm/execution_result.rs +++ b/compiler_tester/src/vm/execution_result.rs @@ -3,7 +3,6 @@ //! use crate::test::case::input::output::Output; -use crate::vm::evm::output::Output as EVMOutput; /// /// The VM execution result. @@ -47,14 +46,3 @@ impl From for ExecutionResult { } } } - -impl From for ExecutionResult { - fn from(output: EVMOutput) -> Self { - Self { - output: Output::from(output), - cycles: 0, - ergs: 0, - gas: 0, - } - } -} diff --git a/compiler_tester/src/vm/mod.rs b/compiler_tester/src/vm/mod.rs index d684425f..7446634b 100644 --- a/compiler_tester/src/vm/mod.rs +++ b/compiler_tester/src/vm/mod.rs @@ -4,6 +4,5 @@ pub mod address_iterator; pub mod eravm; -pub mod evm; pub mod execution_result; pub mod revm; diff --git a/compiler_tester/src/vm/evm/address_iterator.rs b/compiler_tester/src/vm/revm/address_iterator.rs similarity index 100% rename from compiler_tester/src/vm/evm/address_iterator.rs rename to compiler_tester/src/vm/revm/address_iterator.rs diff --git a/compiler_tester/src/vm/revm/balance.rs b/compiler_tester/src/vm/revm/balance.rs index 5c8904dc..35ef0f4b 100644 --- a/compiler_tester/src/vm/revm/balance.rs +++ b/compiler_tester/src/vm/revm/balance.rs @@ -5,14 +5,14 @@ use revm::{ primitives::{EVMError, Env, InvalidTransaction, KECCAK_EMPTY, U256}, }; -use super::{revm_type_conversions::web3_address_to_revm_address, Revm}; +use super::{revm_type_conversions::web3_address_to_revm_address, REVM}; use revm::Database; -impl<'a> Revm<'a> { +impl<'a> REVM<'a> { /// /// All accounts used to deploy the test contracts should have a balance of U256::MAX. /// - pub fn update_deploy_balance(mut self, account: &web3::types::Address) -> Revm<'a> { + pub fn update_deploy_balance(mut self, account: &web3::types::Address) -> REVM<'a> { let address = web3_address_to_revm_address(account); let nonce = match self.state.db_mut().basic(address) { Ok(Some(acc)) => acc.nonce, @@ -33,7 +33,7 @@ impl<'a> Revm<'a> { .modify_env(|env| env.clone_from(&Box::new(Env::default()))) .build(); new_state.transact_commit().ok(); // Even if TX fails, the balance update will be committed - Revm { state: new_state } + REVM { state: new_state } } /// @@ -59,14 +59,14 @@ impl<'a> Revm<'a> { }) .build(); new_state.transact_commit().ok(); - Revm { state: new_state } + REVM { state: new_state } } /// /// REVM needs to send a transaction to execute a contract call, /// the balance of the caller is updated to have enough funds to send the transaction. /// - pub fn update_balance_if_lack_of_funds(mut self, caller: web3::types::Address) -> Revm<'a> { + pub fn update_balance_if_lack_of_funds(mut self, caller: web3::types::Address) -> REVM<'a> { if let Err(EVMError::Transaction(InvalidTransaction::LackOfFundForMaxFee { fee, balance: _balance, @@ -89,7 +89,7 @@ impl<'a> Revm<'a> { ); }) .build(); - Revm { state: new_state } + REVM { state: new_state } } else { Self { state: self.state } } @@ -99,7 +99,7 @@ impl<'a> Revm<'a> { /// If the caller is not a rich address, subtract the fee /// from the balance used only to previoulsy send the transaction. /// - pub fn non_rich_update_balance(mut self, caller: web3::types::Address) -> Revm<'a> { + pub fn non_rich_update_balance(mut self, caller: web3::types::Address) -> REVM<'a> { let post_balance = self .state .context @@ -126,6 +126,6 @@ impl<'a> Revm<'a> { }) .build(); let _ = new_state.transact_commit(); - Revm { state: new_state } + REVM { state: new_state } } } diff --git a/compiler_tester/src/vm/revm/init.rs b/compiler_tester/src/vm/revm/init.rs index 4d95b39a..59684c2f 100644 --- a/compiler_tester/src/vm/revm/init.rs +++ b/compiler_tester/src/vm/revm/init.rs @@ -1,4 +1,8 @@ -use std::{convert::Infallible, str::FromStr}; +use std::str::FromStr; +use std::convert::Infallible; +use std::path::PathBuf; +use std::time::Duration; +use std::time::Instant; use revm::{ db::{states::plain_account::PlainStorage, EmptyDBTyped}, @@ -13,8 +17,12 @@ use super::revm_type_conversions::{ web3_address_to_revm_address, web3_u256_to_revm_address, web3_u256_to_revm_u256, }; +/// +/// REVM instance with its internal state. +/// #[derive(Debug)] pub struct Revm<'a> { + /// REVM internal state. pub state: Evm<'a, (), revm::State>>, } @@ -83,6 +91,38 @@ impl<'a> Revm<'a> { } } + /// + /// Downloads the necessary compiler executables. + /// + pub fn download(executable_download_config_paths: Vec) -> anyhow::Result<()> { + let mut http_client_builder = reqwest::blocking::ClientBuilder::new(); + http_client_builder = http_client_builder.connect_timeout(Duration::from_secs(60)); + http_client_builder = http_client_builder.pool_idle_timeout(Duration::from_secs(60)); + http_client_builder = http_client_builder.timeout(Duration::from_secs(60)); + let http_client = http_client_builder.build()?; + + let download_time_start = Instant::now(); + println!( + " {} compiler executables", + "Downloading".bright_green().bold() + ); + for config_path in executable_download_config_paths.into_iter() { + era_compiler_downloader::Downloader::new(http_client.clone()) + .download(config_path.as_path())?; + } + println!( + " {} downloading compiler executables in {}m{:02}s", + "Finished".bright_green().bold(), + download_time_start.elapsed().as_secs() / 60, + download_time_start.elapsed().as_secs() % 60, + ); + + Ok(()) + } + + /// + /// Fills a runtime transaction with the given parameters. + /// pub fn fill_runtime_new_transaction( self, address: web3::types::Address, @@ -119,6 +159,9 @@ impl<'a> Revm<'a> { Self { state: vm } } + /// + /// Fills a deploy transaction with the given parameters. + /// pub fn fill_deploy_new_transaction( self, caller: web3::types::Address, diff --git a/compiler_tester/src/vm/evm/input/build.rs b/compiler_tester/src/vm/revm/input/build.rs similarity index 100% rename from compiler_tester/src/vm/evm/input/build.rs rename to compiler_tester/src/vm/revm/input/build.rs diff --git a/compiler_tester/src/vm/evm/input/mod.rs b/compiler_tester/src/vm/revm/input/mod.rs similarity index 100% rename from compiler_tester/src/vm/evm/input/mod.rs rename to compiler_tester/src/vm/revm/input/mod.rs diff --git a/compiler_tester/src/vm/revm/mod.rs b/compiler_tester/src/vm/revm/mod.rs index fe3f6490..433821d6 100644 --- a/compiler_tester/src/vm/revm/mod.rs +++ b/compiler_tester/src/vm/revm/mod.rs @@ -1,5 +1,206 @@ +pub mod address_iterator; pub mod balance; -pub mod init; +pub mod input; pub mod revm_type_conversions; -pub use init::Revm; +use std::convert::Infallible; +use std::path::PathBuf; +use std::str::FromStr; +use std::time::Duration; +use std::time::Instant; + +use colored::Colorize; +use revm::{ + db::{states::plain_account::PlainStorage, EmptyDBTyped}, + primitives::{Address, FixedBytes, TxKind, B256, U256}, + Evm, +}; + +use solidity_adapter::EVMVersion; + +use crate::{test::case::input::calldata::Calldata, vm::eravm::system_context::SystemContext}; + +use self::revm_type_conversions::{ + web3_address_to_revm_address, web3_u256_to_revm_address, web3_u256_to_revm_u256, +}; + +/// +/// REVM instance with its internal state. +/// +#[derive(Debug)] +pub struct REVM<'a> { + /// REVM internal state. + pub state: Evm<'a, (), revm::State>>, +} + +impl<'a> Default for REVM<'a> { + fn default() -> Self { + Self::new() + } +} + +impl<'a> REVM<'a> { + /// + /// A shortcut constructor. + /// + pub fn new() -> Self { + let mut cache = revm::CacheState::new(false); + // Precompile 0x01 needs to have its code hash + let acc_info = revm::primitives::AccountInfo { + balance: U256::from(1_u64), + code_hash: FixedBytes::from_str( + "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + ) + .expect("Always valid"), + code: None, + nonce: 1, + }; + + cache.insert_account_with_storage( + Address::from_word(FixedBytes::from(U256::from(1_u64))), + acc_info, + PlainStorage::default(), + ); + + // Account 0x00 needs to have its code hash on 0 + let acc_info_zero = revm::primitives::AccountInfo { + balance: U256::from(0_u64), + code_hash: FixedBytes::from(U256::ZERO), + code: None, + nonce: 1, + }; + + cache.insert_account_with_storage( + Address::from_word(FixedBytes::from(U256::ZERO)), + acc_info_zero, + PlainStorage::default(), + ); + + let mut state = revm::db::State::builder() + .with_cached_prestate(cache) + .with_bundle_update() + .build(); + + // Blocks 0 and 1 need to have their hashes set (revm by default just uses the keccak of the number) + state.block_hashes.insert( + 1, + B256::from_str("0x3737373737373737373737373737373737373737373737373737373737373737") + .unwrap(), + ); + state.block_hashes.insert( + 0, + B256::from_str("0x3737373737373737373737373737373737373737373737373737373737373737") + .unwrap(), + ); + + Self { + state: revm::Evm::builder().with_db(state).build(), + } + } + + /// + /// Downloads the necessary compiler executables. + /// + pub fn download(executable_download_config_paths: Vec) -> anyhow::Result<()> { + let mut http_client_builder = reqwest::blocking::ClientBuilder::new(); + http_client_builder = http_client_builder.connect_timeout(Duration::from_secs(60)); + http_client_builder = http_client_builder.pool_idle_timeout(Duration::from_secs(60)); + http_client_builder = http_client_builder.timeout(Duration::from_secs(60)); + let http_client = http_client_builder.build()?; + + let download_time_start = Instant::now(); + println!( + " {} compiler executables", + "Downloading".bright_green().bold() + ); + for config_path in executable_download_config_paths.into_iter() { + era_compiler_downloader::Downloader::new(http_client.clone()) + .download(config_path.as_path())?; + } + println!( + " {} downloading compiler executables in {}m{:02}s", + "Finished".bright_green().bold(), + download_time_start.elapsed().as_secs() / 60, + download_time_start.elapsed().as_secs() % 60, + ); + + Ok(()) + } + + /// + /// Fills a deploy transaction with the given parameters. + /// + pub fn fill_deploy_new_transaction( + self, + caller: web3::types::Address, + value: Option, + evm_version: Option, + code: Vec, + ) -> Self { + let vm = self + .state + .modify() + .modify_env(|env| { + let evm_context = SystemContext::get_constants_evm(evm_version); + env.cfg.chain_id = evm_context.chain_id; + env.block.number = U256::from(evm_context.block_number); + let coinbase = web3::types::U256::from_str_radix(evm_context.coinbase, 16).unwrap(); + env.block.coinbase = web3_u256_to_revm_address(coinbase); + env.block.timestamp = U256::from(evm_context.block_timestamp); + env.block.gas_limit = U256::from(evm_context.block_gas_limit); + env.block.basefee = U256::from(evm_context.base_fee); + let block_difficulty = + web3::types::U256::from_str_radix(evm_context.block_difficulty, 16).unwrap(); + env.block.difficulty = web3_u256_to_revm_u256(block_difficulty); + env.block.prevrandao = Some(B256::from(env.block.difficulty)); + env.tx.gas_price = U256::from(0xb2d05e00_u32); + env.tx.gas_limit = evm_context.block_gas_limit; + env.tx.access_list = vec![]; + env.tx.caller = web3_address_to_revm_address(&caller); + env.tx.data = revm::primitives::Bytes::from(code); + env.tx.value = revm::primitives::U256::from(value.unwrap_or_default()); + env.tx.transact_to = TxKind::Create; + }) + .build(); + Self { state: vm } + } + + /// + /// Fills a runtime transaction with the given parameters. + /// + pub fn fill_runtime_new_transaction( + self, + address: web3::types::Address, + caller: web3::types::Address, + calldata: Calldata, + value: Option, + evm_version: Option, + ) -> Self { + let vm = self + .state + .modify() + .modify_env(|env| { + let evm_context = SystemContext::get_constants_evm(evm_version); + env.tx.caller = web3_address_to_revm_address(&caller); + env.tx.data = revm::primitives::Bytes::from(calldata.inner.clone()); + env.tx.value = revm::primitives::U256::from(value.unwrap_or_default()); + env.tx.transact_to = TxKind::Call(web3_address_to_revm_address(&address)); + env.cfg.chain_id = evm_context.chain_id; + env.block.number = U256::from(evm_context.block_number); + let coinbase = web3::types::U256::from_str_radix(evm_context.coinbase, 16).unwrap(); + env.block.coinbase = web3_u256_to_revm_address(coinbase); + env.block.timestamp = U256::from(evm_context.block_timestamp); + env.block.gas_limit = U256::from(evm_context.block_gas_limit); + env.block.basefee = U256::from(evm_context.base_fee); + let block_difficulty = + web3::types::U256::from_str_radix(evm_context.block_difficulty, 16).unwrap(); + env.block.difficulty = web3_u256_to_revm_u256(block_difficulty); + env.block.prevrandao = Some(B256::from(env.block.difficulty)); + env.tx.gas_price = U256::from(0xb2d05e00_u32); + env.tx.gas_limit = evm_context.block_gas_limit; + env.tx.access_list = vec![]; + }) + .build(); + Self { state: vm } + } +}