diff --git a/Cargo.lock b/Cargo.lock index 27d8519c8d..b2ca997a29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,7 +8,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" dependencies = [ - "getrandom 0.2.7", + "getrandom 0.2.6", "once_cell", "version_check", ] @@ -172,7 +172,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55f9480d25c1283e8806b280f65e885b4fb840e8e8d72b784401233c9bd83202" dependencies = [ - "getrandom 0.2.7", + "getrandom 0.2.6", "js-sys", "primitive-types 0.11.1", "rustc-hex", @@ -700,14 +700,14 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if 1.0.0", "js-sys", "libc", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi 0.10.2+wasi-snapshot-preview1", "wasm-bindgen", ] @@ -755,9 +755,9 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "hashbrown" -version = "0.12.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "607c8a29735385251a339424dd462993c0fed8fa09d378f259377df08c126022" +checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758" dependencies = [ "ahash", ] @@ -1003,9 +1003,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "js-sys" -version = "0.3.58" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04" dependencies = [ "wasm-bindgen", ] @@ -1437,9 +1437,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58" dependencies = [ "lock_api", "parking_lot_core 0.9.1", @@ -1785,7 +1785,7 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.2.7", + "getrandom 0.2.6", ] [[package]] @@ -1830,7 +1830,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ - "getrandom 0.2.7", + "getrandom 0.2.6", "redox_syscall", ] @@ -1903,10 +1903,10 @@ dependencies = [ "auto_impl", "bytes", "futures", - "hashbrown 0.12.2", + "hashbrown 0.12.0", "hex", "num_enum", - "parking_lot 0.12.1", + "parking_lot 0.12.0", "primitive-types 0.11.1", "revm_precompiles", "rlp", @@ -1936,7 +1936,7 @@ dependencies = [ "num", "primitive-types 0.11.1", "ripemd", - "secp256k1 0.23.3", + "secp256k1 0.23.4", "sha2 0.10.2", "sha3 0.10.1", "substrate-bn", @@ -1948,7 +1948,7 @@ version = "0.2.0" dependencies = [ "bytes", "hash-db", - "hashbrown 0.12.2", + "hashbrown 0.12.0", "hex", "indicatif", "plain_hasher", @@ -1972,7 +1972,7 @@ version = "0.2.0" dependencies = [ "bn-rs", "bytes", - "getrandom 0.2.7", + "getrandom 0.2.6", "hex", "js-sys", "primitive-types 0.11.1", @@ -2080,9 +2080,9 @@ dependencies = [ [[package]] name = "secp256k1" -version = "0.23.3" +version = "0.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77cb4e47e3ccff9a1e168471c11e026c067f50ea7c11bf5e877cae505fb743a0" +checksum = "6ece73253dd9e1fb540ff324eae554113a31c25fb598d22fd13b088a6a03f90d" dependencies = [ "secp256k1-sys 0.6.0", ] @@ -2148,18 +2148,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.138" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" +checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.138" +version = "1.0.136" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" +checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" dependencies = [ "proc-macro2", "quote", @@ -2168,9 +2168,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" dependencies = [ "itoa 1.0.1", "ryu", @@ -2395,9 +2395,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.92" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff7c592601f11445996a06f8ad0c27f094a58857c2f89e97974ab9235b92c52" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ "proc-macro2", "quote", @@ -2504,18 +2504,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ "proc-macro2", "quote", @@ -2794,15 +2794,15 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.81" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2810,9 +2810,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.81" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca" dependencies = [ "bumpalo", "lazy_static", @@ -2837,9 +2837,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.81" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2847,9 +2847,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.81" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc" dependencies = [ "proc-macro2", "quote", @@ -2860,9 +2860,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.81" +version = "0.2.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2" [[package]] name = "web-sys" @@ -2894,7 +2894,7 @@ dependencies = [ "jsonrpc-core", "log", "once_cell", - "parking_lot 0.12.1", + "parking_lot 0.12.0", "pin-project", "reqwest", "rlp", diff --git a/README.md b/README.md index c979e4a16a..b5b4e20527 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ -# revm - Revolutionary Machine +# revm - Rust Ethereum Virtual Machine -Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM` (got opcodes/interp from here), `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). - -It is fast and flexible implementation of EVM with simple interface and embedded Host, there are multiple things done on Host part from const EVM Spec to optimistic changelogs for subroutines to merging `eip2929` in EVM state so that it can be accesses only once that are improving the speed of execution. There are still some improvements on Interpreter part that needs to be done so that we can be comparable with evmone, for more info track [this issue](https://github.com/bluealloy/revm/issues/7). +Is EVM written in rust that is focused on **speed** and **simplicity**. It has fast and flexible implementation with simple interface and embedded Host. It is passing all `ethereum/tests` test suits Here is list of things that i would like to use as guide in this project: - **EVM compatibility and stability** - this goes without saying but it is nice to put it here. In blockchain industry, stability is most desired attribute of any system. @@ -10,6 +8,36 @@ Here is list of things that i would like to use as guide in this project: - **Simplicity** - simplification of internals so that it can be easily understood and extended, and interface that can be easily used or integrated into other project. - **interfacing** - `[no_std]` so that it can be used as wasm lib and integrate with JavaScript and cpp binding if needed. -Read more on REVM here [crates/revm/README.md](crates/revm/README.md) +# Project structure + +* crates + * revm -> main EVM library + * revm_precompiles -> EVM precompiles are standalone + * revmjs -> Binding for js. (in not finished state) +* bins: + * revme: cli binary, used for running state test json + * revm-test: test binaries with contracts, used mostly to checke performance (will proably merge it inside revme). +# Running eth tests + +go to `cd bins/revme/` + +Download eth tests from (this will take some time): `git clone https://github.com/ethereum/tests` + +run tests with command: `cargo run --release -- statetest tests/GeneralStateTests/` + +`GeneralStateTests` contains all tests related to EVM. + +# Used by + +* Foundry: https://github.com/foundry-rs/foundry + +(If you want to add your project to the list, ping me or open the PR) + + +# Contact + +There is public telegram group: https://t.me/+Ig4WDWOzikA3MzA0 + +Or you can contact me directly on email: dragan0rakita@gmail.com + -For executable binary that contains `debuger`, `statetest` for running eth/tests, and `runner` check REVME at [bin/revme/README.md](bins/revme/README.md) diff --git a/bins/revm-test/Cargo.toml b/bins/revm-test/Cargo.toml index 0b3eaf26b4..bcdbff414b 100644 --- a/bins/revm-test/Cargo.toml +++ b/bins/revm-test/Cargo.toml @@ -9,3 +9,7 @@ bytes = "1.1" hex = "0.4" primitive-types = { version = "0.11", features = ["rlp"] } revm = { path = "../../crates/revm", version="1.3" } + + +[[bin]] +name = "analysis" \ No newline at end of file diff --git a/bins/revm-test/src/bin/analysis.rs b/bins/revm-test/src/bin/analysis.rs new file mode 100644 index 0000000000..7c62f18cf8 --- /dev/null +++ b/bins/revm-test/src/bin/analysis.rs @@ -0,0 +1,59 @@ +use std::{str::FromStr, time::Instant}; + +use bytes::Bytes; +use primitive_types::H160; +use revm::{db::BenchmarkDB, Bytecode, TransactTo}; + +extern crate alloc; + +pub fn simple_example() { + //let contract_data : Bytes = hex::decode("608060405234801561001057600080fd5b506004361061004c5760003560e01c806330627b7c1461005157806375ac892a14610085578063784f13661461011d578063c294360114610146575b600080fd5b610059610163565b604080516001600160f81b03199485168152928416602084015292168183015290519081900360600190f35b6100a86004803603604081101561009b57600080fd5b50803590602001356102d1565b6040805160208082528351818301528351919283929083019185019080838360005b838110156100e25781810151838201526020016100ca565b50505050905090810190601f16801561010f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6100596004803603606081101561013357600080fd5b508035906020810135906040013561055b565b6100a86004803603602081101561015c57600080fd5b5035610590565b6000806000610176610400610300610834565b60405180606001604052806001546000546207d5dc028161019357fe5b058152600060208083018290526040928301919091528251600b81905583820151600c81905593830151600d819055835160608082018652928152808401959095528484015282519081018352600654815260075491810191909152600854918101919091526102259161021c916102139161020e91612ef7565b612f64565b6207d5dc612feb565b620f424061301e565b8051600e556020810151600f55604001516010556102416142dd565b61025a816102556102006101806008613064565b613212565b90506102708161025561014561021c6008613064565b905061028481610255610258806008613064565b905061029a8161025561020a61020c6008613064565b90506102a781600461301e565b90506102b1613250565b8051602082015160409092015160f891821b9692821b9550901b92509050565b606060005b6000548112156104c95760006102ed828686613064565b90506002816000015160f81b90808054603f811680603e811461032a576002830184556001831661031c578192505b600160028404019350610342565b600084815260209081902060ff198516905560419094555b505050600190038154600116156103685790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816020015160f81b90808054603f811680603e81146103c557600283018455600183166103b7578192505b6001600284040193506103dd565b600084815260209081902060ff198516905560419094555b505050600190038154600116156104035790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816040015160f81b90808054603f811680603e81146104605760028301845560018316610452578192505b600160028404019350610478565b600084815260209081902060ff198516905560419094555b5050506001900381546001161561049e5790600052602060002090602091828204019190065b815460ff601f929092036101000a9182021916600160f81b90930402919091179055506001016102d6565b506002805460408051602060018416156101000260001901909316849004601f8101849004840282018401909252818152929183018282801561054d5780601f106105225761010080835404028352916020019161054d565b820191906000526020600020905b81548152906001019060200180831161053057829003601f168201915b505050505090505b92915050565b60008060008061056c878787613064565b8051602082015160409092015160f891821b9a92821b9950901b9650945050505050565b600154606090600019015b600081126107a35760005b6000548112156107995760006105bd828487613064565b90506002816000015160f81b90808054603f811680603e81146105fa57600283018455600183166105ec578192505b600160028404019350610612565b600084815260209081902060ff198516905560419094555b505050600190038154600116156106385790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816020015160f81b90808054603f811680603e81146106955760028301845560018316610687578192505b6001600284040193506106ad565b600084815260209081902060ff198516905560419094555b505050600190038154600116156106d35790600052602060002090602091828204019190065b909190919091601f036101000a81548160ff02191690600160f81b840402179055506002816040015160f81b90808054603f811680603e81146107305760028301845560018316610722578192505b600160028404019350610748565b600084815260209081902060ff198516905560419094555b5050506001900381546001161561076e5790600052602060002090602091828204019190065b815460ff601f929092036101000a9182021916600160f81b90930402919091179055506001016105a6565b506000190161059b565b506002805460408051602060018416156101000260001901909316849004601f810184900484028201840190925281815292918301828280156108275780601f106107fc57610100808354040283529160200191610827565b820191906000526020600020905b81548152906001019060200180831161080a57829003601f168201915b505050505090505b919050565b8160008190555080600181905550604051806080016040528060405180606001604052806302faf08081526020016303197500815260200163119e7f8081525081526020016108a460405180606001604052806000815260200161a673198152602001620f423f19815250612f64565b815260006020808301829052604092830182905283518051600355808201516004558301516005558381015180516006559081015160075582015160085582820151600955606092830151600a805460ff1916911515919091179055815192830190915260015490548291906207d5dc028161091c57fe5b058152600060208083018290526040928301919091528251600b81905583820151600c81905593830151600d819055835160608082018652928152808401959095528484015282519081018352600654815260075491810191909152600854918101919091526109979161021c916102139161020e91612ef7565b8051600e55602080820151600f55604091820151601055815160a08101835264174876e8008152825160608082018552641748862a40825263026e8f00828501526304dd1e008286015282840191825284518082018652600080825281860181905281870181905284870191825286518084018852620b71b081526203d09081880181905281890152928501928352608085018181526011805460018082018355919093528651600b9093027f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c688101938455955180517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c69880155808901517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6a8801558901517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6b870155925180517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6c870155808801517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6d8701558801517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6e860155925180517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c6f860155958601517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c7085015594909501517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c71830155517f31ecc21a745e3968a04e9570e4425bc18fa8019c68028196b546d1669c200c72909101805492949192909160ff1990911690836002811115610c1057fe5b0217905550505060116040518060a0016040528064174876e8008152602001604051806060016040528064174290493f19815260200163026e8f0081526020016304dd1e008152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806203d09081526020016203d0908152602001620b71b0815250815260200160006002811115610cb657fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff1990921691908490811115610d5857fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200163026e8f00815260200164174876e800815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620b71b08152602001620b71b08152602001620b71b0815250815260200160006002811115610dfd57fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff1990921691908490811115610e9f57fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200163026e8f00815260200164173e54e97f1981525081526020016040518060600160405280600081526020016000815260200160008152508152602001604051806060016040528060008152602001600081526020016000815250815260200160006002811115610f3f57fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff1990921691908490811115610fe157fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200164174876e80081526020016304dd1e00815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620b71b08152602001620b71b08152602001620b71b081525081526020016000600281111561108657fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff199092169190849081111561112857fe5b0217905550505060116040518060a0016040528064174876e800815260200160405180606001604052806302faf080815260200164174399c9ff1981526020016304dd1e00815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620b71b08152602001620b71b08152602001620b71b08152508152602001600060028111156111ce57fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff199092169190849081111561127057fe5b0217905550505060116040518060a0016040528062fbc5208152602001604051806060016040528063019bfcc0815260200162fbc52081526020016302cd29c0815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561131157fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff19909216919084908111156113b357fe5b0217905550505060116040518060a001604052806323c34600815260200160405180606001604052806302faf080815260200163289c455081526020016304dd1e008152508152602001604051806060016040528062b71b00815260200162b71b00815260200162b71b00815250815260200160405180606001604052806000815260200160008152602001600081525081526020016000600281111561145657fe5b905281546001818101845560009384526020938490208351600b90930201918255838301518051838301558085015160028085019190915560409182015160038501558185015180516004860155808701516005860155820151600685015560608501518051600786015595860151600885015594015160098301556080830151600a83018054949593949193909260ff19909216919084908111156114f857fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016305a1f4a081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561160c57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff19909216919084908111156116fd57fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016305a1f4a08152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561180e57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff19909216919084908111156118ff57fe5b0217905550505060126040518060e001604052806040518060600160405280630555a9608152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016305a1f4a08152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115611a1357fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115611b0457fe5b0217905550505060126040518060e001604052806040518060600160405280630555a960815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016305a1f4a081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115611c1557fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115611d0657fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016303aa6a608152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115611e1a57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115611f0b57fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016303aa6a6081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561201c57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561210d57fe5b0217905550505060126040518060e001604052806040518060600160405280630555a9608152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016303aa6a6081525081526020016040518060600160405280630459e44081526020016302f34f6081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561222157fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561231257fe5b0217905550505060126040518060e001604052806040518060600160405280630555a960815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001600081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016303aa6a608152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561242357fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561251457fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016303aa6a6081525081526020016040518060600160405280630555a9608152602001630188c2e081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561262857fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561271957fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f208152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630555a9608152602001630188c2e081526020016304a62f8081525081526020016040518060600160405280630459e4408152602001630188c2e081526020016305a1f4a08152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e5881525081526020016001600281111561282d57fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff199092169190849081111561291e57fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630555a960815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016303aa6a608152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115612a3257fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115612b2357fe5b0217905550505060126040518060e00160405280604051806060016040528063035e1f20815260200163016a8c8081526020016304a62f8081525081526020016040518060600160405280630459e440815260200163016a8c8081526020016305a1f4a081525081526020016040518060600160405280630555a960815260200163016a8c8081526020016304a62f808152508152602001604051806060016040528060008152602001600081526020016000815250815260200160405180606001604052806000815260200160008152602001600081525081526020016040518060600160405280620f3e588152602001620f3e588152602001620f3e58815250815260200160016002811115612c3757fe5b905281546001818101845560009384526020938490208351805160139094029091019283558085015183830155604090810151600280850191909155858501518051600386015580870151600486015582015160058501558185015180516006860155808701516007860155820151600885015560608501518051600986015580870151600a860155820151600b85015560808501518051600c86015580870151600d860155820151600e85015560a08501518051600f860155958601516010850155940151601183015560c0830151601283018054949593949193909260ff1990921691908490811115612d2857fe5b0217905550505060005b601254811015612ef257600060128281548110612d4b57fe5b600091825260209182902060408051610140810182526013909302909101805460e08401908152600182015461010085015260028083015461012086015290845282516060818101855260038401548252600484015482880152600584015482860152858701919091528351808201855260068401548152600784015481880152600884015481860152858501528351808201855260098401548152600a84015481880152600b840154818601528186015283518082018552600c8401548152600d84015481880152600e84015481860152608086015283519081018452600f830154815260108301549581019590955260118201549285019290925260a0830193909352601283015491929160c084019160ff90911690811115612e6c57fe5b6002811115612e7757fe5b815250509050612eac61020e612e95836020015184600001516132cd565b612ea7846040015185600001516132cd565b612ef7565b60128381548110612eb957fe5b60009182526020918290208351600960139093029091019182015590820151600a820155604090910151600b9091015550600101612d32565b505050565b612eff6142dd565b604051806060016040528083602001518560400151028460400151866020015102038152602001836040015185600001510284600001518660400151020381526020018360000151856020015102846020015186600001510203815250905092915050565b612f6c6142dd565b604082015160208301518351600092612f9292918002918002919091019080020161330c565b90506040518060600160405280828560000151620f42400281612fb157fe5b058152602001828560200151620f42400281612fc957fe5b058152602001828560400151620f42400281612fe157fe5b0590529392505050565b612ff36142dd565b5060408051606081018252835183028152602080850151840290820152928101519091029082015290565b6130266142dd565b60405180606001604052808385600001518161303e57fe5b0581526020018385602001518161305157fe5b05815260200183856040015181612fe157fe5b61306c6142dd565b6000546013805463ffffffff1916918502860163ffffffff169190911790556130936142dd565b905060005b828112156131f157600061317261314c61021c613115600b60405180606001604052908160008201548152602001600182015481526020016002820154815250506207a1206000546207a1206130ec613343565b63ffffffff16816130f957fe5b0663ffffffff168d620f424002018161310e57fe5b0503612feb565b60408051606081018252600e548152600f5460208201526010549181019190915260015461025591906207a12090816130ec613343565b604080516060810182526006548152600754602082015260085491810191909152613212565b6040805160e081019091526003546080820190815260045460a083015260055460c083015291925060009181906131ae9061025586608c612feb565b81526020016131bc84612f64565b815260006020820181905260409091015290506131e5846102556131df8461336c565b8861301e565b93505050600101613098565b5061320861021c61320183613753565b60ff612feb565b90505b9392505050565b61321a6142dd565b50604080516060810182528251845101815260208084015181860151019082015291810151928101519092019181019190915290565b60008080556001819055613266906002906142fe565b60006003819055600481905560058190556006819055600781905560088190556009819055600a805460ff19169055600b819055600c819055600d819055600e819055600f81905560108190556132bf90601190614345565b6132cb60126000614366565b565b6132d56142dd565b5060408051606081018252825184510381526020808401518186015103908201528282015184830151039181019190915292915050565b80600260018201055b8181121561333d5780915060028182858161332c57fe5b05018161333557fe5b059050613315565b50919050565b6013805463ffffffff19811663ffffffff9182166341c64e6d0261303901821617918290551690565b6133746142dd565b600a826040015113156133a657604051806060016040528060008152602001600081526020016000815250905061082f565b60008060006133b48561379f565b91945092509050826133e857604051806060016040528060008152602001600081526020016000815250935050505061082f565b6133f0614387565b6133f86143c7565b6134006142dd565b6134086142dd565b600086600181111561341657fe5b1415613505576011858154811061342957fe5b60009182526020918290206040805160a081018252600b90930290910180548352815160608082018452600183015482526002808401548388015260038401548386015285870192909252835180820185526004840154815260058401548188015260068401548186015285850152835180820185526007840154815260088401549681019690965260098301549386019390935291830193909352600a830154919291608084019160ff909116908111156134e157fe5b60028111156134ec57fe5b8152505093508360600151915083604001519050613653565b6012858154811061351257fe5b600091825260209182902060408051610140810182526013909302909101805460e08401908152600182015461010085015260028083015461012086015290845282516060818101855260038401548252600484015482880152600584015482860152858701919091528351808201855260068401548152600784015481880152600884015481860152858501528351808201855260098401548152600a84015481880152600b840154818601528186015283518082018552600c8401548152600d84015481880152600e84015481860152608086015283519081018452600f830154815260108301549581019590955260118201549285019290925260a0830193909352601283015491929160c084019160ff9091169081111561363357fe5b600281111561363e57fe5b8152505092508260a001519150826080015190505b6040820151600190811215613669575060408201515b808360200151131561367c575060208201515b808360400151131561368f575060408201515b60408a01805160010190819052600512156136f75780620f42406136b1613343565b63ffffffff16816136be57fe5b0663ffffffff1612156136e8576136e16136db84620f4240612feb565b8261301e565b92506136f7565b50965061082f95505050505050565b6136ff6142dd565b600088600181111561370d57fe5b14156137255761371e8b878b613a57565b9050613733565b6137308b868b613aec565b90505b6137448361025561021c8785613baa565b9b9a5050505050505050505050565b61375b6142dd565b60405180606001604052806137738460000151613be8565b81526020016137858460200151613be8565b81526020016137978460400151613be8565b905292915050565b60008080808080805b6011548110156138c2576000613890601183815481106137c457fe5b60009182526020918290206040805160a081018252600b90930290910180548352815160608082018452600183015482526002808401548388015260038401548386015285870192909252835180820185526004840154815260058401548188015260068401548186015285850152835180820185526007840154815260088401549681019690965260098301549386019390935291830193909352600a830154919291608084019160ff9091169081111561387c57fe5b600281111561388757fe5b9052508a613c13565b90506000811380156138a957508415806138a957508481125b156138b957809450600093508192505b506001016137a8565b5060005b601254811015613a49576000613a17601283815481106138e257fe5b600091825260209182902060408051610140810182526013909302909101805460e08401908152600182015461010085015260028083015461012086015290845282516060818101855260038401548252600484015482880152600584015482860152858701919091528351808201855260068401548152600784015481880152600884015481860152858501528351808201855260098401548152600a84015481880152600b840154818601528186015283518082018552600c8401548152600d84015481880152600e84015481860152608086015283519081018452600f830154815260108301549581019590955260118201549285019290925260a0830193909352601283015491929160c084019160ff90911690811115613a0357fe5b6002811115613a0e57fe5b9052508a613cbb565b9050600081138015613a305750841580613a3057508481125b15613a4057809450600193508192505b506001016138c6565b509196909550909350915050565b613a5f6142dd565b6000613a7a856000015161025561021c886020015187612feb565b90506000613a8f61020e8387602001516132cd565b9050600085608001516002811115613aa357fe5b1415613ae1576000613ab9828860200151613e0c565b12613acd57613aca81600019612feb565b90505b613ad8868383613e31565b9250505061320b565b613ad8868383613fc1565b613af46142dd565b6000613b0f856000015161025561021c886020015187612feb565b6060860151909150620a2c2a9015613b2757506216e3605b6000620f4240613b3f87606001518960200151613e0c565b81613b4657fe5b05905060008112613b55576000035b64e8d4a5100081800281038380020281900590036000811215613b8c57613b8188858960600151613fc1565b94505050505061320b565b613b9e88858960600151868686614039565b98975050505050505050565b613bb26142dd565b50604080516060810182528251845102815260208084015181860151029082015291810151928101519092029181019190915290565b600080821215613bfa5750600061082f565b620f4240821315613c0f5750620f424061082f565b5090565b600080613c28846020015184600001516132cd565b90506000620f4240613c3e838660200151613e0c565b81613c4557fe5b865191900591506000908002613c5b8480613e0c565b838402030190506000811215613c775760009350505050610555565b613c808161330c565b90506103e88183031315613c9957900391506105559050565b6103e88183011315613caf570191506105559050565b50600095945050505050565b600080613cd0846020015185600001516132cd565b90506000613ce6856040015186600001516132cd565b90506000613cf8856020015183612ef7565b90506000620f4240613d0a8584613e0c565b81613d1157fe5b0590506103e71981138015613d2757506103e881125b15613d39576000945050505050610555565b85518751600091613d49916132cd565b9050600082613d588386613e0c565b81613d5f57fe5b0590506000811280613d735750620f424081135b15613d875760009650505050505050610555565b6000613d938388612ef7565b9050600084613da68b6020015184613e0c565b81613dad57fe5b0590506000811280613dc35750620f4240818401135b15613dd957600098505050505050505050610555565b600085613de68985613e0c565b81613ded57fe5b0590506103e88112156137445760009950505050505050505050610555565b6040808201519083015160208084015190850151845186510291020191020192915050565b613e396142dd565b6000620f424080613e48613343565b63ffffffff1681613e5557fe5b0663ffffffff16625fdfb00281613e6857fe5b0590506000620f4240613e79613343565b63ffffffff1681613e8657fe5b0663ffffffff1690506000613e9a8261330c565b6103e8029050613ea86142dd565b620186a0613eb98760000151614216565b1315613ee657604051806060016040528060008152602001620f4240815260200160008152509050613f09565b6040518060600160405280620f4240815260200160008152602001600081525090505b613f1661020e8288612ef7565b90506000613f2761020e8884612ef7565b9050613f7f61020e613f64613f5285620f424088613f448c61422e565b0281613f4c57fe5b05612feb565b61025585620f424089613f448d61424e565b6102558a613f7689620f42400361330c565b6103e802612feb565b9150613fb460405180608001604052808a81526020018481526020018b6040015181526020018b60600151151581525061336c565b9998505050505050505050565b613fc96142dd565b6000613ffb61020e8660200151613ff686620f4240613fec898c60200151613e0c565b60020281613f4c57fe5b6132cd565b90506140306040518060800160405280868152602001838152602001876040015181526020018760600151151581525061336c565b95945050505050565b6140416142dd565b60608701516000199015614053575060015b600061408961020e61021c61406c8c602001518a612feb565b613ff68b6140798a61330c565b620f42408c8e0205018802612feb565b60608a0151909150620f42408601906140ba57620f42406140aa838a613e0c565b816140b157fe5b05620f42400390505b60408a0151619c406c0c9f2c9cd04674edea40000000620ea6008480028502850285020205019060021261415e5761412a61411f60405180608001604052808d81526020018681526020018e6040015181526020018e6060015115151581525061336c565b82620f424003612feb565b92506141448361025561413e8e8e8e613fc1565b84612feb565b925061415383620f424061301e565b94505050505061420c565b600281056203d09001620f4240614173613343565b63ffffffff168161418057fe5b0663ffffffff1612156141b2576141536141a461419e8d8d8d613fc1565b83612feb565b600283056203d0900161301e565b6142056141f76141ec60405180608001604052808e81526020018781526020018f6040015181526020018f6060015115151581525061336c565b83620f424003612feb565b60028305620b71b00361301e565b9450505050505b9695505050505050565b60008082131561422757508061082f565b5060000390565b60008061423a8361424e565b905061320b81820264e8d4a510000361330c565b60005b600082121561426757625fdfb082019150614251565b5b625fdfb0821261427f57625fdfb082039150614268565b6001828160025b818313156142d457818385028161429957fe5b0585019450620f4240808788860202816142af57fe5b05816142b757fe5b600095909503940592506001810181029190910290600201614286565b50505050919050565b60405180606001604052806000815260200160008152602001600081525090565b50805460018160011615610100020316600290046000825580601f106143245750614342565b601f0160209004906000526020600020908101906143429190614401565b50565b50805460008255600b02906000526020600020908101906143429190614416565b50805460008255601302906000526020600020908101906143429190614475565b6040518060a00160405280600081526020016143a16142dd565b81526020016143ae6142dd565b81526020016143bb6142dd565b81526020016000905290565b6040518060e001604052806143da6142dd565b81526020016143e76142dd565b81526020016143f46142dd565b81526020016143a16142dd565b5b80821115613c0f5760008155600101614402565b5b80821115613c0f57600080825560018201819055600282018190556003820181905560048201819055600582018190556006820181905560078201819055600882018190556009820155600a8101805460ff19169055600b01614417565b5b80821115613c0f576000808255600182018190556002820181905560038201819055600482018190556005820181905560068201819055600782018190556008820181905560098201819055600a8201819055600b8201819055600c8201819055600d8201819055600e8201819055600f820181905560108201819055601182015560128101805460ff1916905560130161447656fea2646970667358221220037024f5647853879c58fbcc61ac3616455f6f731cc6e84f91eb5a3b4e06c00464736f6c63430007060033").unwrap().into(); +} + +fn main() { + let contract_data : Bytes = hex::decode( "6060604052341561000f57600080fd5b604051610dd1380380610dd18339810160405280805190602001909190805182019190602001805190602001909190805182019190505083600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508360008190555082600390805190602001906100a79291906100e3565b5081600460006101000a81548160ff021916908360ff16021790555080600590805190602001906100d99291906100e3565b5050505050610188565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061012457805160ff1916838001178555610152565b82800160010185558215610152579182015b82811115610151578251825591602001919060010190610136565b5b50905061015f9190610163565b5090565b61018591905b80821115610181576000816000905550600101610169565b5090565b90565b610c3a806101976000396000f3006060604052600436106100af576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806306fdde03146100b4578063095ea7b31461014257806318160ddd1461019c57806323b872dd146101c557806327e235e31461023e578063313ce5671461028b5780635c658165146102ba57806370a082311461032657806395d89b4114610373578063a9059cbb14610401578063dd62ed3e1461045b575b600080fd5b34156100bf57600080fd5b6100c76104c7565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101075780820151818401526020810190506100ec565b50505050905090810190601f1680156101345780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561014d57600080fd5b610182600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610565565b604051808215151515815260200191505060405180910390f35b34156101a757600080fd5b6101af610657565b6040518082815260200191505060405180910390f35b34156101d057600080fd5b610224600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803590602001909190505061065d565b604051808215151515815260200191505060405180910390f35b341561024957600080fd5b610275600480803573ffffffffffffffffffffffffffffffffffffffff169060200190919050506108f7565b6040518082815260200191505060405180910390f35b341561029657600080fd5b61029e61090f565b604051808260ff1660ff16815260200191505060405180910390f35b34156102c557600080fd5b610310600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610922565b6040518082815260200191505060405180910390f35b341561033157600080fd5b61035d600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610947565b6040518082815260200191505060405180910390f35b341561037e57600080fd5b610386610990565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156103c65780820151818401526020810190506103ab565b50505050905090810190601f1680156103f35780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561040c57600080fd5b610441600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091908035906020019091905050610a2e565b604051808215151515815260200191505060405180910390f35b341561046657600080fd5b6104b1600480803573ffffffffffffffffffffffffffffffffffffffff1690602001909190803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610b87565b6040518082815260200191505060405180910390f35b60038054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561055d5780601f106105325761010080835404028352916020019161055d565b820191906000526020600020905b81548152906001019060200180831161054057829003601f168201915b505050505081565b600081600260003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925846040518082815260200191505060405180910390a36001905092915050565b60005481565b600080600260008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020541015801561072e5750828110155b151561073957600080fd5b82600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254019250508190555082600160008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156108865782600260008773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825403925050819055505b8373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef856040518082815260200191505060405180910390a360019150509392505050565b60016020528060005260406000206000915090505481565b600460009054906101000a900460ff1681565b6002602052816000526040600020602052806000526040600020600091509150505481565b6000600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b60058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610a265780601f106109fb57610100808354040283529160200191610a26565b820191906000526020600020905b815481529060010190602001808311610a0957829003601f168201915b505050505081565b600081600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000205410151515610a7e57600080fd5b81600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254039250508190555081600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040518082815260200191505060405180910390a36001905092915050565b6000600260008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050929150505600a165627a7a72305820df254047bc8f2904ad3e966b6db116d703bebd40efadadb5e738c836ffc8f58a0029" ).unwrap().into(); + + // BenchmarkDB is dummy state that implements Database trait. + let mut evm = revm::new(); + + // execution globals block hash/gas_limit/coinbase/timestamp.. + evm.env.tx.caller = H160::from_str("0x1000000000000000000000000000000000000000").unwrap(); + evm.env.tx.transact_to = + TransactTo::Call(H160::from_str("0x0000000000000000000000000000000000000000").unwrap()); + //evm.env.tx.data = Bytes::from(hex::decode("30627b7c").unwrap()); + evm.env.tx.data = Bytes::from(hex::decode("8035F0CE").unwrap()); + evm.env.cfg.perf_all_precompiles_have_balance = true; + + let bytecode_raw = Bytecode::new_raw(contract_data.clone()); + let bytecode_checked = Bytecode::new_raw(contract_data.clone()).to_checked(); + let bytecode_analysed = Bytecode::new_raw(contract_data).to_analysed::(); + + evm.database(BenchmarkDB::new_bytecode(bytecode_raw)); + + // just to spead up processor. + for _ in 0..10000 { + let (_, _, _, _, _) = evm.transact(); + } + + let timer = Instant::now(); + for _ in 0..30000 { + let (_, _, _, _, _) = evm.transact(); + } + println!("Raw elapsed time: {:?}", timer.elapsed()); + + evm.database(BenchmarkDB::new_bytecode(bytecode_checked)); + + let timer = Instant::now(); + for _ in 0..30000 { + let (_, _, _, _, _) = evm.transact(); + } + println!("Checked elapsed time: {:?}", timer.elapsed()); + + evm.database(BenchmarkDB::new_bytecode(bytecode_analysed)); + + let timer = Instant::now(); + for _ in 0..30000 { + let (_, _, _, _, _) = evm.transact(); + } + println!("Analysed elapsed time: {:?}", timer.elapsed()); +} diff --git a/bins/revm-test/src/main.rs b/bins/revm-test/src/main.rs index 167ff55502..5f59bda380 100644 --- a/bins/revm-test/src/main.rs +++ b/bins/revm-test/src/main.rs @@ -2,7 +2,7 @@ use std::{str::FromStr, time::Instant}; use bytes::Bytes; use primitive_types::H160; -use revm::{db::BenchmarkDB, TransactTo}; +use revm::{db::BenchmarkDB, Bytecode, TransactTo}; extern crate alloc; @@ -11,7 +11,7 @@ pub fn simple_example() { // BenchmarkDB is dummy state that implements Database trait. let mut evm = revm::new(); - evm.database(BenchmarkDB(contract_data)); + evm.database(BenchmarkDB::new_bytecode(Bytecode::new_raw(contract_data))); // execution globals block hash/gas_limit/coinbase/timestamp.. evm.env.tx.caller = H160::from_str("0x1000000000000000000000000000000000000000").unwrap(); @@ -29,7 +29,9 @@ pub fn simple_example() { elapsed += i; } println!("elapsed: {:?}", elapsed / 30); - for (i, time) in times.iter().enumerate() { + let mut times = times[5..].to_vec(); + times.sort(); + for (i, time) in times.iter().rev().enumerate() { println!("{}: {:?}", i, time); } } diff --git a/bins/revme/src/debugger/ctrl/ctrl.rs b/bins/revme/src/debugger/ctrl/ctrl.rs index b9bc472d53..b947e48f22 100644 --- a/bins/revme/src/debugger/ctrl/ctrl.rs +++ b/bins/revme/src/debugger/ctrl/ctrl.rs @@ -135,7 +135,8 @@ impl Inspector for Controller { CtrlPrint::All => { let opcode = interp .contract - .code + .bytecode + .bytecode() .get(interp.program_counter()) .cloned() .unwrap(); @@ -154,7 +155,12 @@ impl Inspector for Controller { ); } CtrlPrint::Opcode => { - let opcode = *interp.contract.code.get(interp.program_counter()).unwrap(); + let opcode = *interp + .contract + .bytecode + .bytecode() + .get(interp.program_counter()) + .unwrap(); println!( "PC:{} OpCode: {:#x} {:?}", interp.program_counter(), diff --git a/bins/revme/src/statetest/models/spec.rs b/bins/revme/src/statetest/models/spec.rs index 44d2462f10..e5a8bd4663 100644 --- a/bins/revme/src/statetest/models/spec.rs +++ b/bins/revme/src/statetest/models/spec.rs @@ -26,6 +26,7 @@ pub enum SpecName { impl SpecName { pub fn to_spec_id(&self) -> SpecId { match self { + Self::Merge => SpecId::MERGE, Self::London => SpecId::LONDON, Self::Berlin => SpecId::BERLIN, Self::Istanbul => SpecId::ISTANBUL, diff --git a/bins/revme/src/statetest/runner.rs b/bins/revme/src/statetest/runner.rs index 3bb4936209..106fedaa6d 100644 --- a/bins/revme/src/statetest/runner.rs +++ b/bins/revme/src/statetest/runner.rs @@ -11,7 +11,7 @@ use sha3::{Digest, Keccak256}; use indicatif::ProgressBar; use primitive_types::{H160, H256, U256}; -use revm::{db::AccountState, CreateScheme, Env, SpecId, TransactTo}; +use revm::{db::AccountState, Bytecode, CreateScheme, Env, SpecId, TransactTo}; use std::sync::atomic::Ordering; use walkdir::{DirEntry, WalkDir}; @@ -47,17 +47,13 @@ pub fn find_all_json_tests(path: &Path) -> Vec { } pub fn execute_test_suit(path: &Path, elapsed: &Arc>) -> Result<(), TestError> { - // funky test with bigint value in json :) + // funky test with `bigint` value in json :) not possible to happen on mainnet and hard to parse. + // https://github.com/ethereum/tests/issues/971 if path.file_name() == Some(OsStr::new("ValueOverflow.json")) { return Ok(()); } - // test with very high nonce that in revm overflows. Impossible to happen. - // https://github.com/bluealloy/revm/issues/28 - if path.file_name() == Some(OsStr::new("CREATE2_HighNonceDelegatecall.json")) { - return Ok(()); - } /* - Test that take a lot of time so we are going to skip them + These tests are passing, but they take a lot of time to execute so we are going to skip them. */ if path.file_name() == Some(OsStr::new("loopExp.json")) { return Ok(()); @@ -74,7 +70,11 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc>) -> Result< if path.file_name() == Some(OsStr::new("CALLBlake2f_MaxRounds.json")) { return Ok(()); } - // failed tests they are missing some arguments + // */ + // /* + // Skip test where basefee/accesslist is present but it shoulnd not be supported. + // https://github.com/ethereum/tests/blob/5b7e1ab3ffaf026d99d20b17bb30f533a2c80c8b/GeneralStateTests/stExample/eip1559.json#L130 + // It is expected to skip these tests. if path.file_name() == Some(OsStr::new("accessListExample.json")) { return Ok(()); } @@ -84,14 +84,17 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc>) -> Result< if path.file_name() == Some(OsStr::new("eip1559.json")) { return Ok(()); } - //*/ let json_reader = std::fs::read(&path).unwrap(); let suit: TestSuit = serde_json::from_reader(&*json_reader)?; let skip_test_unit: HashSet<_> = vec![ - "typeTwoBerlin", //txbyte is of type 02 and we dont parse bytes for this test to fail as it + "typeTwoBerlin", //txbyte is of type 02 and we dont parse bytes for this test to fail. "CREATE2_HighNonce", //testing nonce > u64::MAX not really possible on mainnet. "CREATE_HighNonce", //testing nonce > u64::MAX not really possible on mainnet. + "CreateTransactionHighNonce", // testing nonce >u64::MAX not really possible on mainnet. code: https://github.com/ethereum/tests/blob/5b7e1ab3ffaf026d99d20b17bb30f533a2c80c8b/BlockchainTests/GeneralStateTests/stCreateTest/CreateTransactionHighNonce.json#L74 + "CREATE2_HighNonceDelegatecall", // test with very high nonce that in revm overflows. Impossible to happen. https://github.com/bluealloy/revm/issues/28 + "doubleSelfdestructTouch", // CHECK THIS + "mergeTest", // CHECK THIS ] .into_iter() .collect(); @@ -136,7 +139,7 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc>) -> Result< let acc_info = revm::AccountInfo { balance: info.balance, code_hash: H256::from_slice(Keccak256::digest(&info.code).as_slice()), //try with dummy hash. - code: Some(info.code.clone()), + code: Some(Bytecode::new_raw(info.code.clone())), nonce: info.nonce, }; database.insert_account_info(*address, acc_info); @@ -171,7 +174,7 @@ pub fn execute_test_suit(path: &Path, elapsed: &Arc>) -> Result< for (spec_name, tests) in unit.post { if !matches!( spec_name, - SpecName::London | SpecName::Berlin | SpecName::Istanbul + SpecName::Merge | SpecName::London | SpecName::Berlin | SpecName::Istanbul ) { continue; } diff --git a/bins/revme/src/statetest/trace.rs b/bins/revme/src/statetest/trace.rs index f8d70f0315..0b81571939 100644 --- a/bins/revme/src/statetest/trace.rs +++ b/bins/revme/src/statetest/trace.rs @@ -78,7 +78,7 @@ impl Inspector for CustomPrintTracer { self.reduced_gas_block = 0; self.full_gas_block = interp.contract.gas_block(pc); } else { - self.reduced_gas_block += info.gas; + self.reduced_gas_block += info.get_gas() as u64; } Return::Continue diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 9e6d82edf5..d30f869ff8 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -7,6 +7,7 @@ license = "MIT" name = "revm" repository = "https://github.com/bluealloy/revm" version = "1.7.0" +readme = "../../README.md" [dependencies] arrayref = "0.3" @@ -20,7 +21,7 @@ parking_lot = { version = "0.12", optional = true } primitive-types = { version = "0.11", default-features = false, features = ["rlp"] } revm_precompiles = { path = "../revm_precompiles", version = "1.1", default-features = false } rlp = { version = "0.5", default-features = false }#used for create2 address calculation -serde = { version = "1.0", features = ["derive"], optional = true } +serde = { version = "1.0", features = ["derive","rc"], optional = true } sha3 = { version = "0.10", default-features = false } tokio = { version = "1.14", features = ["rt-multi-thread", "macros"], optional = true } web3 = { version = "0.18", optional = true } diff --git a/crates/revm/README.md b/crates/revm/README.md deleted file mode 100644 index 7f0ae8d808..0000000000 --- a/crates/revm/README.md +++ /dev/null @@ -1,92 +0,0 @@ -# revm - Revolutionary Machine - -Is **Rust Ethereum Virtual Machine** with great name that is focused on **speed** and **simplicity**. It gets ispiration from `SputnikVM`, `OpenEthereum` and `Geth` with a help from [wolflo/evm-opcodes](https://github.com/wolflo/evm-opcodes). This is probably one of the fastest implementation of EVM, from const EVM Spec to optimistic changelogs for subroutines to merging `eip2929` in EVM state so that it can be accesses only once are some of the things that are improving the speed of execution. - -Here is list of things that i would like to use as guide in this project: -- **EVM compatibility and stability** - this goes without saying but it is nice to put it here. In blockchain industry, stability is most desired attribute of any system. -- **Speed** - is one of the most important things and most decision are made to complement this. -- **Simplicity** - simplification of internals so that it can be easily understood and extended, and interface that can be easily used or integrated into other project. -- **interfacing** - `[no_std]` so that it can be used as wasm lib and integrate with JavaScript and cpp binding if needed. - -## Usage - -Please check `bins/revm-test` for simple use case. - -All ethereum state tests can be found `bins/revm-ethereum-tests` and can be run with `cargo run --release -- all` - -Example with creating simple set/get smartcontract and calling create and two calls: -```rust - let caller = H160::from_str("0x1000000000000000000000000000000000000000").unwrap(); - // InMemoryDB is db that implements Database trait. - // add one account and some eth for testing. - let mut evm = revm::new(); - evm.database(InMemoryDB::new()); - evm.db().unwrap().insert_cache( - caller.clone(), - AccountInfo { - nonce: 1, - balance: U256::from(10000000), - code: None, - code_hash: KECCAK_EMPTY, - }, - ); - - // execution globals block hash/gas_limit/coinbase/timestamp.. - evm.env.tx.caller = caller.clone(); - - evm.env.tx.transact_to = TransactTo::create(); - evm.env.tx.data = Bytes::from(hex::decode("608060405234801561001057600080fd5b50610150806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80632e64cec11461003b5780636057361d14610059575b600080fd5b610043610075565b60405161005091906100d9565b60405180910390f35b610073600480360381019061006e919061009d565b61007e565b005b60008054905090565b8060008190555050565b60008135905061009781610103565b92915050565b6000602082840312156100b3576100b26100fe565b5b60006100c184828501610088565b91505092915050565b6100d3816100f4565b82525050565b60006020820190506100ee60008301846100ca565b92915050565b6000819050919050565b600080fd5b61010c816100f4565b811461011757600080fd5b5056fea2646970667358221220404e37f487a89a932dca5e77faaf6ca2de3b991f93d230604b1b8daaef64766264736f6c63430008070033").unwrap()); - - let (_, out, _) = evm.transact(); - let contract_address = match out { - TransactOut::Create(_, Some(add)) => add, - _ => panic!("not gona happen"), - }; - - evm.env.tx.transact_to = TransactTo::Call(contract_address); - evm.env.tx.data = - hex::decode("6057361d0000000000000000000000000000000000000000000000000000000000000015") - .unwrap() - .into(); - evm.transact(); - - evm.env.tx.transact_to = TransactTo::Call(contract_address); - evm.env.tx.data = hex::decode("2e64cec1").unwrap().into(); - - let (_, out, _) = evm.transact(); - - println!("get value (StaticCall): {:?}\n", out); -``` -## Status of project - -I just started this project as a hobby to kill some time. Presenty it has good structure and I would like to finish it and make it functional but we will see how far we will go. If you want to use this project be free to contact me and we can talk. There are a lot of things that still needs to be done, here are some of TODO's that could be added: - -- integrate ethereum state tests: it is passing Instanbul, Berlin, London tests. -- Need to cleanup code and do some refactoring -- Write a lot of comments and explanations. -- Add MemoryCache for Database interface. -- Write a lot of rust tests -- wasm interface -- C++ interface -## Project structure: - -The structure of the project is getting crystallized and we can see few parts that are worthy to write about: -- `Spec` contains a specification of Ethereum standard. It is made as a trait so that it can be optimized away by the compiler -- `instructions` have one main function `eval` and takes `Interpreter`, `EVM Host`, `Spec` and `opcode` and depending on opcode it does calculation or for various opcodes it call `Host` for subroutine handling. This is where execution happens and where we cancluate gas consumption. -- `interepter` contains memory and execution stack of smart contracts. It calls opcode for execution and contains `step` function. It reads the contract, extracts opcodes and handles memory. -- `subroutine` for various calls/creates we need to have separate `interp` and separate accessed locations. This is place where all of this is done, additionaly, it contains all caches of accessed accounts/slots/code. EIP2929 related access is integrated into state memory. Getting inside new call `subroutine` creates checkpoint that contain needed information that can revert state if subcall reverts or needs to be discardet. Changeset is made so it is optimistic that means that we dont do any work if call is finished successfully and only do something when it fials. -- `EVMImpl`- Is main entry to the lib,it implements `Host` and connects `subroutine` and `interpreter` and does `subroutine checkpoint` switches. - - -### Subroutine - -Changelogs are created in every subroutine and represent action that needs to happen so that present state can be reverted to state before subroutine. It contains list of accounts with original values that can be used to revert current state to state before this subroutine started. - -Depending on subroutine and if account was previously loaded/destryoyed, accounts in changelog can be: -- LoadedCold -> when reverting, remove account from state. -- Dirty(_) -> account is already hot, and in this subroutine we are changing it. Field needed for that are: - - original_slot: HashMap: - SlotChangeLog can be: ColdLoad or Dirty(H256) - - info: (original balance/nonce/code) - - was_cold: bool -- Destroyed(Account) -> swap all Info and Storage from current state diff --git a/crates/revm/src/db.rs b/crates/revm/src/db.rs index de2d8a5b30..a1779f1d90 100644 --- a/crates/revm/src/db.rs +++ b/crates/revm/src/db.rs @@ -7,20 +7,19 @@ pub use web3db::Web3DB; pub use in_memory_db::{AccountState, BenchmarkDB, CacheDB, DbAccount, EmptyDB, InMemoryDB}; -use crate::Account; +use crate::{interpreter::bytecode::Bytecode, Account}; use hashbrown::HashMap as Map; use primitive_types::{H160, H256, U256}; use crate::AccountInfo; use auto_impl::auto_impl; -use bytes::Bytes; #[auto_impl(& mut, Box)] pub trait Database { /// Get basic account information. fn basic(&mut self, address: H160) -> AccountInfo; /// Get account code by its hash - fn code_by_hash(&mut self, code_hash: H256) -> Bytes; + fn code_by_hash(&mut self, code_hash: H256) -> Bytecode; /// Get storage value of address at index. fn storage(&mut self, address: H160, index: U256) -> U256; @@ -40,7 +39,7 @@ pub trait DatabaseRef { /// Get basic account information. fn basic(&self, address: H160) -> AccountInfo; /// Get account code by its hash - fn code_by_hash(&self, code_hash: H256) -> Bytes; + fn code_by_hash(&self, code_hash: H256) -> Bytecode; /// Get storage value of address at index. fn storage(&self, address: H160, index: U256) -> U256; @@ -68,7 +67,7 @@ impl<'a> Database for RefDBWrapper<'a> { self.db.basic(address) } /// Get account code by its hash - fn code_by_hash(&mut self, code_hash: H256) -> Bytes { + fn code_by_hash(&mut self, code_hash: H256) -> Bytecode { self.db.code_by_hash(code_hash) } /// Get storage value of address at index. diff --git a/crates/revm/src/db/in_memory_db.rs b/crates/revm/src/db/in_memory_db.rs index ec8de2d30e..5c844f7c7b 100644 --- a/crates/revm/src/db/in_memory_db.rs +++ b/crates/revm/src/db/in_memory_db.rs @@ -1,19 +1,14 @@ -use crate::{Database, Filth, KECCAK_EMPTY}; - +use super::{DatabaseCommit, DatabaseRef}; +use crate::{interpreter::bytecode::Bytecode, Database, Filth, KECCAK_EMPTY}; +use crate::{Account, AccountInfo, Log}; use alloc::{ collections::btree_map::{self, BTreeMap}, vec::Vec, }; use hashbrown::{hash_map::Entry, HashMap as Map}; - use primitive_types::{H160, H256, U256}; - -use crate::{Account, AccountInfo, Log}; -use bytes::Bytes; use sha3::{Digest, Keccak256}; -use super::{DatabaseCommit, DatabaseRef}; - pub type InMemoryDB = CacheDB; impl InMemoryDB { @@ -28,7 +23,7 @@ pub struct CacheDB { /// Dummy account info where `code` is always `None`. /// Code bytes can be found in `contracts`. pub accounts: BTreeMap, - pub contracts: Map, + pub contracts: Map, pub logs: Vec, pub block_hashes: Map, pub db: ExtDB, @@ -57,8 +52,8 @@ pub enum AccountState { impl CacheDB { pub fn new(db: ExtDB) -> Self { let mut contracts = Map::new(); - contracts.insert(KECCAK_EMPTY, Bytes::new()); - contracts.insert(H256::zero(), Bytes::new()); + contracts.insert(KECCAK_EMPTY, Bytecode::new()); + contracts.insert(H256::zero(), Bytecode::new()); Self { accounts: BTreeMap::new(), contracts, @@ -72,9 +67,8 @@ impl CacheDB { let code = core::mem::take(&mut account.code); if let Some(code) = code { if !code.is_empty() { - let code_hash = H256::from_slice(&Keccak256::digest(&code)); - account.code_hash = code_hash; - self.contracts.insert(code_hash, code); + account.code_hash = code.hash(); + self.contracts.insert(account.code_hash, code); } } if account.code_hash.is_zero() { @@ -197,7 +191,7 @@ impl Database for CacheDB { } } - fn code_by_hash(&mut self, code_hash: H256) -> Bytes { + fn code_by_hash(&mut self, code_hash: H256) -> Bytecode { match self.contracts.entry(code_hash) { Entry::Occupied(entry) => entry.get().clone(), Entry::Vacant(entry) => { @@ -239,7 +233,7 @@ impl DatabaseRef for CacheDB { } } - fn code_by_hash(&self, code_hash: H256) -> Bytes { + fn code_by_hash(&self, code_hash: H256) -> Bytecode { match self.contracts.get(&code_hash) { Some(entry) => entry.clone(), None => self.db.code_by_hash(code_hash), @@ -257,8 +251,8 @@ impl DatabaseRef for EmptyDB { AccountInfo::default() } /// Get account code by its hash - fn code_by_hash(&self, _code_hash: H256) -> Bytes { - Bytes::default() + fn code_by_hash(&self, _code_hash: H256) -> Bytecode { + Bytecode::new() } /// Get storage value of address at index. fn storage(&self, _address: H160, _index: U256) -> U256 { @@ -277,7 +271,14 @@ impl DatabaseRef for EmptyDB { /// /// Any other address will return an empty account. #[derive(Debug, Default, Clone)] -pub struct BenchmarkDB(pub Bytes); +pub struct BenchmarkDB(pub Bytecode, H256); + +impl BenchmarkDB { + pub fn new_bytecode(bytecode: Bytecode) -> Self { + let hash = bytecode.hash(); + Self(bytecode, hash) + } +} impl Database for BenchmarkDB { /// Get basic account information. @@ -287,15 +288,15 @@ impl Database for BenchmarkDB { nonce: 1, balance: U256::from(10000000), code: Some(self.0.clone()), - code_hash: KECCAK_EMPTY, + code_hash: self.1, }; } AccountInfo::default() } /// Get account code by its hash - fn code_by_hash(&mut self, _code_hash: H256) -> Bytes { - Bytes::default() + fn code_by_hash(&mut self, _code_hash: H256) -> Bytecode { + Bytecode::default() } /// Get storage value of address at index. diff --git a/crates/revm/src/db/web3db.rs b/crates/revm/src/db/web3db.rs index fb040a3085..e0a7d237bd 100644 --- a/crates/revm/src/db/web3db.rs +++ b/crates/revm/src/db/web3db.rs @@ -1,4 +1,4 @@ -use crate::{AccountInfo, Database, KECCAK_EMPTY}; +use crate::{interpreter::bytecode::Bytecode, AccountInfo, Database, KECCAK_EMPTY}; use bytes::Bytes; use primitive_types::{H160, H256, U256}; use tokio::runtime::{Handle, Runtime}; @@ -67,14 +67,14 @@ impl Database for Web3DB { nonce .unwrap_or_else(|e| panic!("web3 get nonce error:{:?}", e)) .as_u64(), - Bytes::from( + Bytecode::new_raw(Bytes::from( code.unwrap_or_else(|e| panic!("web3 get node error:{:?}", e)) .0, - ), + )), ) } - fn code_by_hash(&mut self, _code_hash: primitive_types::H256) -> bytes::Bytes { + fn code_by_hash(&mut self, _code_hash: primitive_types::H256) -> Bytecode { panic!("Should not be called. Code is already loaded"); // not needed because we already load code with basic info } diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index c1f4d28436..3add0aedf8 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -3,7 +3,7 @@ use crate::{ evm_impl::{EVMImpl, Transact}, subroutine::State, BerlinSpec, ByzantiumSpec, Env, Inspector, IstanbulSpec, LatestSpec, Log, LondonSpec, - NoOpInspector, Return, Spec, SpecId, TransactOut, + MergeSpec, NoOpInspector, Return, Spec, SpecId, TransactOut, }; use alloc::{boxed::Box, vec::Vec}; use revm_precompiles::Precompiles; @@ -155,6 +155,7 @@ pub fn evm_inner<'a, DB: Database, const INSPECT: bool>( ) -> Box { match env.cfg.spec_id { SpecId::LATEST => create_evm!(LatestSpec, db, env, insp), + SpecId::MERGE => create_evm!(MergeSpec, db, env, insp), SpecId::LONDON => create_evm!(LondonSpec, db, env, insp), SpecId::BERLIN => create_evm!(BerlinSpec, db, env, insp), SpecId::ISTANBUL => create_evm!(IstanbulSpec, db, env, insp), diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index bdea4ae741..e255682220 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -1,6 +1,7 @@ use crate::{ db::Database, - gas, interpreter, + gas, + interpreter::{self, bytecode::Bytecode}, interpreter::{Contract, Interpreter}, models::SelfDestructResult, return_ok, @@ -363,7 +364,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, // Create new interpreter and execute initcode let contract = Contract::new::( Bytes::new(), - inputs.init_code.clone(), + Bytecode::new_raw(inputs.init_code.clone()), created_address, inputs.caller, inputs.value, @@ -390,10 +391,10 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, return_ok!() => { let b = Bytes::new(); // if ok, check contract creation limit and calculate gas deduction on output len. - let code = interp.return_value(); + let bytes = interp.return_value(); // EIP-3541: Reject new contract code starting with the 0xEF byte - if SPEC::enabled(LONDON) && !code.is_empty() && code.first() == Some(&0xEF) { + if SPEC::enabled(LONDON) && !bytes.is_empty() && bytes.first() == Some(&0xEF) { self.data.subroutine.checkpoint_revert(checkpoint); return (Return::CreateContractWithEF, ret, interp.gas, b); } @@ -407,12 +408,12 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, .eip170_contract_code_size_limit; } // EIP-170: Contract code size limit - if SPEC::enabled(SPURIOUS_DRAGON) && code.len() > contract_code_size_limit { + if SPEC::enabled(SPURIOUS_DRAGON) && bytes.len() > contract_code_size_limit { self.data.subroutine.checkpoint_revert(checkpoint); return (Return::CreateContractLimit, ret, interp.gas, b); } if crate::USE_GAS { - let gas_for_code = code.len() as u64 * crate::gas::CODEDEPOSIT; + let gas_for_code = bytes.len() as u64 * crate::gas::CODEDEPOSIT; // record code deposit gas cost and check if we are out of gas. if !interp.gas.record_cost(gas_for_code) { self.data.subroutine.checkpoint_revert(checkpoint); @@ -421,10 +422,12 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } // if we have enought gas self.data.subroutine.checkpoint_commit(); - let code_hash = H256::from_slice(Keccak256::digest(&code).as_slice()); + // Do analasis of bytecode streight away. + let bytecode = Bytecode::new_raw(bytes).to_analysed::(); + let code_hash = bytecode.hash(); self.data .subroutine - .set_code(created_address, code, code_hash); + .set_code(created_address, bytecode, code_hash); (Return::Continue, ret, interp.gas, b) } _ => { @@ -461,7 +464,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, let mut gas = Gas::new(inputs.gas_limit); // Load account and get code. Account is now hot. - let (code, _) = self.code(inputs.contract); + let (bytecode, _) = self.code(inputs.contract); // Check depth if self.data.subroutine.depth() > interpreter::CALL_STACK_LIMIT { @@ -545,7 +548,7 @@ impl<'a, GSPEC: Spec, DB: Database, const INSPECT: bool> EVMImpl<'a, GSPEC, DB, } else { // Create interpreter and execute subcall let contract = - Contract::new_with_context::(inputs.input.clone(), code, &inputs.context); + Contract::new_with_context::(inputs.input.clone(), bytecode, &inputs.context); #[cfg(feature = "memory_limit")] let mut interp = Interpreter::new_with_memory_limit::( @@ -618,7 +621,7 @@ impl<'a, GSPEC: Spec, DB: Database + 'a, const INSPECT: bool> Host (balance, is_cold) } - fn code(&mut self, address: H160) -> (Bytes, bool) { + fn code(&mut self, address: H160) -> (Bytecode, bool) { let (acc, is_cold) = self.data.subroutine.load_code(address, self.data.db); (acc.info.code.clone().unwrap(), is_cold) } @@ -721,7 +724,7 @@ pub trait Host { /// Get balance of address. fn balance(&mut self, address: H160) -> (U256, bool); /// Get code of address. - fn code(&mut self, address: H160) -> (Bytes, bool); + fn code(&mut self, address: H160) -> (Bytecode, bool); /// Get code hash of address. fn code_hash(&mut self, address: H160) -> (H256, bool); /// Get storage value of address at index. diff --git a/crates/revm/src/instructions/control.rs b/crates/revm/src/instructions/control.rs index acb94ac7d1..d84f8efcae 100644 --- a/crates/revm/src/instructions/control.rs +++ b/crates/revm/src/instructions/control.rs @@ -8,7 +8,7 @@ pub fn jump(interp: &mut Interpreter) -> Return { if interp.contract.is_valid_jump(dest) { // Safety: In analysis we are checking create our jump table and we do check above to be // sure that jump is safe to execute. - interp.program_counter = unsafe { interp.contract.code.as_ptr().add(dest) }; + interp.program_counter = unsafe { interp.contract.bytecode.as_ptr().add(dest) }; Return::Continue } else { Return::InvalidJump @@ -23,7 +23,7 @@ pub fn jumpi(interp: &mut Interpreter) -> Return { if interp.contract.is_valid_jump(dest) { // Safety: In analysis we are checking if jump is valid destination and // this `if` makes this unsafe block safe. - interp.program_counter = unsafe { interp.contract.code.as_ptr().add(dest) }; + interp.program_counter = unsafe { interp.contract.bytecode.as_ptr().add(dest) }; Return::Continue } else { Return::InvalidJump diff --git a/crates/revm/src/instructions/host.rs b/crates/revm/src/instructions/host.rs index 71e1a3bd90..a8926d4a53 100644 --- a/crates/revm/src/instructions/host.rs +++ b/crates/revm/src/instructions/host.rs @@ -82,7 +82,7 @@ pub fn extcodecopy(interp: &mut Interpreter, host: &mut H) // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it interp .memory - .set_data(memory_offset, code_offset, len, &code); + .set_data(memory_offset, code_offset, len, code.bytes()); Return::Continue } diff --git a/crates/revm/src/instructions/opcode.rs b/crates/revm/src/instructions/opcode.rs index 01f3fb965c..5d20371f41 100644 --- a/crates/revm/src/instructions/opcode.rs +++ b/crates/revm/src/instructions/opcode.rs @@ -168,74 +168,63 @@ impl OpCode { self.0 } } + +const JUMP_MASK: u32 = 0x80000000; +const GAS_BLOCK_END_MASK: u32 = 0x40000000; +const IS_PUSH_MASK: u32 = 0x20000000; +const GAS_MASK: u32 = 0x1FFFFFFF; + #[derive(Debug)] pub struct OpInfo { - pub gas: u64, - pub is_jump: bool, - pub is_gas_block_end: bool, - pub is_push: bool, + /// Data contains few information packed inside u32: + /// IS_JUMP (1bit) | IS_GAS_BLOCK_END (1bit) | IS_PUSH (1bit) | gas (29bits) + data: u32, } impl OpInfo { + #[inline(always)] pub fn is_jump(&self) -> bool { - self.is_jump + self.data & JUMP_MASK == JUMP_MASK } - + #[inline(always)] pub fn is_gas_block_end(&self) -> bool { - self.is_gas_block_end + self.data & GAS_BLOCK_END_MASK == GAS_BLOCK_END_MASK } - + #[inline(always)] pub fn is_push(&self) -> bool { - self.is_push + self.data & IS_PUSH_MASK == IS_PUSH_MASK + } + + #[inline(always)] + pub fn get_gas(&self) -> u32 { + self.data & GAS_MASK } pub const fn none() -> Self { - Self { - gas: 0, - is_jump: false, - is_gas_block_end: false, - is_push: false, - } + Self { data: 0 } } + pub const fn gas_block_end(gas: u64) -> Self { Self { - gas, - is_jump: false, - is_gas_block_end: true, - is_push: false, + data: gas as u32 | GAS_BLOCK_END_MASK, } } pub const fn dynamic_gas() -> Self { - Self { - gas: 0, - is_jump: false, - is_gas_block_end: false, - is_push: false, - } + Self { data: 0 } } + pub const fn gas(gas: u64) -> Self { - Self { - gas, - is_jump: false, - is_gas_block_end: false, - is_push: false, - } + Self { data: gas as u32 } } pub const fn push_opcode() -> Self { Self { - gas: gas::VERYLOW, - is_jump: false, - is_gas_block_end: false, - is_push: true, + data: gas::VERYLOW as u32 | IS_PUSH_MASK, } } pub const fn jumpdest() -> Self { Self { - gas: 0, - is_jump: true, - is_gas_block_end: true, - is_push: false, + data: JUMP_MASK | GAS_BLOCK_END_MASK, } } } @@ -543,52 +532,56 @@ macro_rules! gas_opcodee { pub const fn spec_opcode_gas(spec_id: SpecId) -> &'static [OpInfo; 256] { match spec_id { SpecId::FRONTIER => { - gas_opcodee!(O, SpecId::FRONTIER); - O + gas_opcodee!(FRONTIER, SpecId::FRONTIER); + FRONTIER } SpecId::HOMESTEAD => { - gas_opcodee!(O, SpecId::HOMESTEAD); - O + gas_opcodee!(HOMESTEAD, SpecId::HOMESTEAD); + HOMESTEAD } SpecId::TANGERINE => { - gas_opcodee!(O, SpecId::TANGERINE); - O + gas_opcodee!(TANGERINE, SpecId::TANGERINE); + TANGERINE } SpecId::SPURIOUS_DRAGON => { - gas_opcodee!(O, SpecId::SPURIOUS_DRAGON); - O + gas_opcodee!(SPURIOUS_DRAGON, SpecId::SPURIOUS_DRAGON); + SPURIOUS_DRAGON } SpecId::BYZANTIUM => { - gas_opcodee!(O, SpecId::BYZANTIUM); - O + gas_opcodee!(BYZANTIUM, SpecId::BYZANTIUM); + BYZANTIUM } SpecId::CONSTANTINOPLE => { - gas_opcodee!(O, SpecId::CONSTANTINOPLE); - O + gas_opcodee!(CONSTANTINOPLE, SpecId::CONSTANTINOPLE); + CONSTANTINOPLE } SpecId::PETERSBURG => { - gas_opcodee!(O, SpecId::PETERSBURG); - O + gas_opcodee!(PETERSBURG, SpecId::PETERSBURG); + PETERSBURG } SpecId::ISTANBUL => { - gas_opcodee!(O, SpecId::ISTANBUL); - O + gas_opcodee!(ISTANBUL, SpecId::ISTANBUL); + ISTANBUL } SpecId::MUIRGLACIER => { - gas_opcodee!(O, SpecId::MUIRGLACIER); - O + gas_opcodee!(MUIRGLACIER, SpecId::MUIRGLACIER); + MUIRGLACIER } SpecId::BERLIN => { - gas_opcodee!(O, SpecId::BERLIN); - O + gas_opcodee!(BERLIN, SpecId::BERLIN); + BERLIN } SpecId::LONDON => { - gas_opcodee!(O, SpecId::LONDON); - O + gas_opcodee!(LONDON, SpecId::LONDON); + LONDON + } + SpecId::MERGE => { + gas_opcodee!(MERGE, SpecId::MERGE); + MERGE } SpecId::LATEST => { - gas_opcodee!(O, SpecId::LATEST); - O + gas_opcodee!(LATEST, SpecId::LATEST); + LATEST } } } diff --git a/crates/revm/src/instructions/system.rs b/crates/revm/src/instructions/system.rs index bb3d2cd95a..bd68efca39 100644 --- a/crates/revm/src/instructions/system.rs +++ b/crates/revm/src/instructions/system.rs @@ -35,7 +35,7 @@ pub fn caller(interp: &mut Interpreter) -> Return { pub fn codesize(interp: &mut Interpreter) -> Return { // gas!(interp, gas::BASE); - let size = U256::from(interp.contract.code_size); + let size = U256::from(interp.contract.bytecode.len()); push!(interp, size); Return::Continue } @@ -52,9 +52,12 @@ pub fn codecopy(interp: &mut Interpreter) -> Return { memory_resize!(interp, memory_offset, len); // Safety: set_data is unsafe function and memory_resize ensures us that it is safe to call it - interp - .memory - .set_data(memory_offset, code_offset, len, &interp.contract.code); + interp.memory.set_data( + memory_offset, + code_offset, + len, + interp.contract.bytecode.original_bytecode_slice(), + ); Return::Continue } diff --git a/crates/revm/src/interpreter.rs b/crates/revm/src/interpreter.rs index 9f39fef579..c79ac72f5c 100644 --- a/crates/revm/src/interpreter.rs +++ b/crates/revm/src/interpreter.rs @@ -1,7 +1,9 @@ +pub mod bytecode; mod contract; pub(crate) mod memory; mod stack; +pub use bytecode::{Bytecode, BytecodeLocked, BytecodeState}; pub use contract::Contract; pub use memory::Memory; pub use stack::Stack; @@ -40,7 +42,7 @@ impl Interpreter { #[cfg(not(feature = "memory_limit"))] pub fn new(contract: Contract, gas_limit: u64) -> Self { Self { - program_counter: contract.code.as_ptr(), + program_counter: contract.bytecode.as_ptr(), return_range: Range::default(), memory: Memory::new(), stack: Stack::new(), @@ -57,7 +59,7 @@ impl Interpreter { memory_limit: u64, ) -> Self { Self { - program_counter: contract.code.as_ptr(), + program_counter: contract.bytecode.as_ptr(), return_range: Range::default(), memory: Memory::new(), stack: Stack::new(), @@ -96,7 +98,7 @@ impl Interpreter { // Safety: this is just subtraction of pointers, it is safe to do. unsafe { self.program_counter - .offset_from(self.contract.code.as_ptr()) as usize + .offset_from(self.contract.bytecode.as_ptr()) as usize } } diff --git a/crates/revm/src/interpreter/bytecode.rs b/crates/revm/src/interpreter/bytecode.rs new file mode 100644 index 0000000000..a4329f9a17 --- /dev/null +++ b/crates/revm/src/interpreter/bytecode.rs @@ -0,0 +1,270 @@ +use super::contract::{AnalysisData, ValidJumpAddress}; +use crate::{opcode, spec_opcode_gas, Spec, KECCAK_EMPTY}; +use bytes::Bytes; +use primitive_types::H256; +use sha3::{Digest, Keccak256}; +use std::sync::Arc; + +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))] +pub enum BytecodeState { + Raw, + Checked { + len: usize, + }, + Analysed { + len: usize, + jumptable: ValidJumpAddress, + }, +} + +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bytecode { + #[cfg_attr(feature = "with-serde", serde(with = "crate::models::serde_hex_bytes"))] + bytecode: Bytes, + state: BytecodeState, +} + +impl Default for Bytecode { + fn default() -> Self { + Bytecode::new() + } +} + +impl Bytecode { + pub fn new() -> Self { + // bytecode with one STOP opcode + Bytecode { + bytecode: vec![0].into(), + state: BytecodeState::Analysed { + len: 0, + jumptable: ValidJumpAddress::new(Arc::new(Vec::new()), 0), + }, + } + } + + pub fn new_raw(bytecode: Bytes) -> Self { + Self { + bytecode, + state: BytecodeState::Raw, + } + } + + /// Create new checked bytecode + /// + /// # Safety + /// Bytecode need to end with STOP (0x00) opcode as checked bytecode assumes that + /// that it is safe to iterate over bytecode without checking lengths + pub unsafe fn new_checked(bytecode: Bytes, len: usize) -> Self { + Self { + bytecode, + state: BytecodeState::Checked { len }, + } + } + + /// Create new analysed bytecode + /// + /// # Safety + /// Same as new_checked, bytecode needs to end with STOP (0x00) opcode as checked bytecode assumes + /// that it is safe to iterate over bytecode without checking length + pub unsafe fn new_analysed(bytecode: Bytes, len: usize, jumptable: ValidJumpAddress) -> Self { + Self { + bytecode, + state: BytecodeState::Analysed { len, jumptable }, + } + } + + pub fn bytes(&self) -> &Bytes { + &self.bytecode + } + + pub fn hash(&self) -> H256 { + let to_hash = match self.state { + BytecodeState::Raw => self.bytecode.as_ref(), + BytecodeState::Checked { len } => &self.bytecode[..len], + BytecodeState::Analysed { len, .. } => &self.bytecode[..len], + }; + if to_hash.is_empty() { + KECCAK_EMPTY + } else { + H256::from_slice(Keccak256::digest(&to_hash).as_slice()) + } + } + + pub fn is_empty(&self) -> bool { + match self.state { + BytecodeState::Raw => self.bytecode.is_empty(), + BytecodeState::Checked { len } => len == 0, + BytecodeState::Analysed { len, .. } => len == 0, + } + } + + pub fn len(&self) -> usize { + match self.state { + BytecodeState::Raw => self.bytecode.len(), + BytecodeState::Checked { len, .. } => len, + BytecodeState::Analysed { len, .. } => len, + } + } + + pub fn to_checked(self) -> Self { + match self.state { + BytecodeState::Raw => { + let len = self.bytecode.len(); + let mut bytecode: Vec = Vec::from(self.bytecode.as_ref()); + bytecode.resize(len + 33, 0); + Self { + bytecode: bytecode.into(), + state: BytecodeState::Checked { len }, + } + } + _ => self, + } + } + + pub fn to_analysed(self) -> Self { + let (bytecode, len) = match self.state { + BytecodeState::Raw => { + let len = self.bytecode.len(); + let checked = self.to_checked(); + (checked.bytecode, len) + } + BytecodeState::Checked { len } => (self.bytecode, len), + _ => return self, + }; + let jumptable = Self::analyze::(bytecode.as_ref()); + + Self { + bytecode, + state: BytecodeState::Analysed { len, jumptable }, + } + } + + pub fn lock(self) -> BytecodeLocked { + let Bytecode { bytecode, state } = self.to_analysed::(); + if let BytecodeState::Analysed { len, jumptable } = state { + BytecodeLocked { + bytecode, + len, + jumptable, + } + } else { + unreachable!("to_analysed transforms state to analysed"); + } + } + + /// Analyze bytecode to get jumptable and gas blocks. + fn analyze(code: &[u8]) -> ValidJumpAddress { + let opcode_gas = spec_opcode_gas(SPEC::SPEC_ID); + + let mut analysis = ValidJumpAddress { + first_gas_block: 0, + analysis: Arc::new(vec![AnalysisData::none(); code.len()]), + }; + let jumps = Arc::get_mut(&mut analysis.analysis).unwrap(); + + let mut index = 0; + let mut gas_in_block: u32 = 0; + let mut block_start: usize = 0; + + // first gas block + while index < code.len() { + let opcode = unsafe { *code.get_unchecked(index) }; + let info = unsafe { opcode_gas.get_unchecked(opcode as usize) }; + analysis.first_gas_block += info.get_gas(); + + index += if info.is_push() { + ((opcode - opcode::PUSH1) + 2) as usize + } else { + 1 + }; + + if info.is_gas_block_end() { + block_start = index - 1; + if info.is_jump() { + unsafe { + jumps.get_unchecked_mut(block_start).set_is_jump(); + } + } + break; + } + } + + while index < code.len() { + let opcode = unsafe { *code.get_unchecked(index) }; + let info = unsafe { opcode_gas.get_unchecked(opcode as usize) }; + gas_in_block += info.get_gas(); + + if info.is_gas_block_end() { + if info.is_jump() { + unsafe { + jumps.get_unchecked_mut(index).set_is_jump(); + } + } + unsafe { + jumps + .get_unchecked_mut(block_start) + .set_gas_block(gas_in_block); + } + block_start = index; + gas_in_block = 0; + index += 1; + } else { + index += if info.is_push() { + ((opcode - opcode::PUSH1) + 2) as usize + } else { + 1 + }; + } + } + if gas_in_block != 0 { + unsafe { + jumps + .get_unchecked_mut(block_start) + .set_gas_block(gas_in_block); + } + } + analysis + } +} + +pub struct BytecodeLocked { + bytecode: Bytes, + len: usize, + jumptable: ValidJumpAddress, +} + +impl BytecodeLocked { + pub fn as_ptr(&self) -> *const u8 { + self.bytecode.as_ptr() + } + pub fn len(&self) -> usize { + self.len + } + + pub fn is_empty(&self) -> bool { + self.len == 0 + } + + pub fn unlock(self) -> Bytecode { + Bytecode { + bytecode: self.bytecode, + state: BytecodeState::Analysed { + len: self.len, + jumptable: self.jumptable, + }, + } + } + pub fn bytecode(&self) -> &[u8] { + self.bytecode.as_ref() + } + + pub fn original_bytecode_slice(&self) -> &[u8] { + &self.bytecode.as_ref()[..self.len] + } + + pub fn jumptable(&self) -> &ValidJumpAddress { + &self.jumptable + } +} diff --git a/crates/revm/src/interpreter/contract.rs b/crates/revm/src/interpreter/contract.rs index 0559eed655..1531a0faec 100644 --- a/crates/revm/src/interpreter/contract.rs +++ b/crates/revm/src/interpreter/contract.rs @@ -1,24 +1,22 @@ -use crate::{alloc::vec::Vec, opcode::spec_opcode_gas, CallContext, Spec}; +use super::bytecode::{Bytecode, BytecodeLocked}; +use crate::{alloc::vec::Vec, CallContext, Spec}; use bytes::Bytes; use primitive_types::{H160, U256}; - -use crate::instructions::opcode; +use std::sync::Arc; pub struct Contract { /// Contracts data pub input: Bytes, /// Contract code - pub code: Bytes, /// code size of original code. Note that current code is extended with push padding and STOP at end - pub code_size: usize, + /// Precomputed valid jump addresses + pub bytecode: BytecodeLocked, /// Contract address pub address: H160, /// Caller of the EVM. pub caller: H160, /// Value send to contract. pub value: U256, - /// Precomputed valid jump addresses - jumpdest: ValidJumpAddress, } #[derive(Clone, Copy, Debug, Eq, PartialEq)] @@ -28,149 +26,79 @@ pub enum Analysis { None, } +const JUMP_MASK: u32 = 0x80000000; + #[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))] pub struct AnalysisData { - pub is_jumpdest: bool, - pub gas_block: u64, + /// This variable packs two informations: + /// IS_JUMP (1bit) | gas block ( 31bits) + is_jump_and_gas_block: u32, } impl AnalysisData { pub fn none() -> Self { AnalysisData { - is_jumpdest: false, - gas_block: 0, + is_jump_and_gas_block: 0, + //gas_block: 0, } } - pub fn jump_dest() -> Self { - AnalysisData { - is_jumpdest: true, - gas_block: 0, - } + pub fn set_is_jump(&mut self) { + self.is_jump_and_gas_block |= JUMP_MASK; + } + + pub fn set_gas_block(&mut self, gas_block: u32) { + let jump = self.is_jump_and_gas_block & JUMP_MASK; + self.is_jump_and_gas_block = gas_block | jump; } - pub fn is_jump_dest(&self) -> bool { - self.is_jumpdest + pub fn is_jump(&self) -> bool { + self.is_jump_and_gas_block & JUMP_MASK == JUMP_MASK + } + + pub fn gas_block(&self) -> u64 { + (self.is_jump_and_gas_block & (!JUMP_MASK)) as u64 } } impl Contract { pub fn new( input: Bytes, - code: Bytes, + bytecode: Bytecode, address: H160, caller: H160, value: U256, ) -> Self { - let code_size = code.len(); - let (jumpdest, code) = Self::analyze::(code.as_ref()); - - let code = code.into(); + let bytecode = bytecode.lock::(); Self { input, - code, - code_size, + bytecode, address, caller, value, - jumpdest, } } - /// Create a new valid mapping from given code bytes. - /// it gives back ValidJumpAddress and size od needed paddings. - fn analyze(code: &[u8]) -> (ValidJumpAddress, Vec) { - let mut jumps: Vec = Vec::with_capacity(code.len() + 33); - // padding of PUSH32 size plus one for stop - jumps.resize(code.len() + 33, AnalysisData::none()); - //let opcode_gas = LONDON_OPCODES; - let opcode_gas = spec_opcode_gas(SPEC::SPEC_ID); - let mut index = 0; - let mut first_gas_block: u64 = 0; - let mut block_start: usize = 0; - // first gas block - - while index < code.len() { - let opcode = unsafe { *code.get_unchecked(index) }; - let info = unsafe { opcode_gas.get_unchecked(opcode as usize) }; - first_gas_block += info.gas; - - index += if info.is_push { - ((opcode - opcode::PUSH1) + 2) as usize - } else { - 1 - }; - - if info.is_gas_block_end { - block_start = index - 1; - if info.is_jump { - unsafe { - jumps.get_unchecked_mut(block_start).is_jumpdest = true; - } - } - break; - } - } - - let mut gas_in_block: u64 = 0; - while index < code.len() { - let opcode = unsafe { *code.get_unchecked(index) }; - let info = unsafe { opcode_gas.get_unchecked(opcode as usize) }; - gas_in_block += info.gas; - - if info.is_gas_block_end { - if info.is_jump { - unsafe { - jumps.get_unchecked_mut(index).is_jumpdest = true; - } - } - unsafe { - jumps.get_unchecked_mut(block_start).gas_block = gas_in_block; - } - block_start = index; - gas_in_block = 0; - } - - index += if info.is_push { - ((opcode - opcode::PUSH1) + 2) as usize - } else { - 1 - }; - } - if gas_in_block != 0 { - unsafe { - jumps.get_unchecked_mut(block_start).gas_block = gas_in_block; - } - } - let padding = index - code.len(); - // +1 is for forced STOP opcode at the end of contract, it is precausion - // if there is none, and if there is STOP our additional opcode will do nothing. - //jumps.resize(jumps.len() + padding + 1, AnalysisData::none()); - let mut code = code.to_vec(); - code.resize(code.len() + padding + 1, 0); - - (ValidJumpAddress::new(jumps, first_gas_block), code) - } - pub fn is_valid_jump(&self, possition: usize) -> bool { - self.jumpdest.is_valid(possition) + self.bytecode.jumptable().is_valid(possition) } pub fn gas_block(&self, possition: usize) -> u64 { - self.jumpdest.gas_block(possition) + self.bytecode.jumptable().gas_block(possition) } pub fn first_gas_block(&self) -> u64 { - self.jumpdest.first_gas_block + self.bytecode.jumptable().first_gas_block as u64 } pub fn new_with_context( input: Bytes, - code: Bytes, + bytecode: Bytecode, call_context: &CallContext, ) -> Self { Self::new::( input, - code, + bytecode, call_context.address, call_context.caller, call_context.apparent_value, @@ -180,13 +108,16 @@ impl Contract { /// Mapping of valid jump destination from code. #[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))] pub struct ValidJumpAddress { - first_gas_block: u64, - analysis: Vec, + pub first_gas_block: u32, + /// Rc is used here so that we dont need to copy vector. We can move it to more suitable more accessable structure + /// without copying underlying vec. + pub analysis: Arc>, } impl ValidJumpAddress { - pub fn new(analysis: Vec, first_gas_block: u64) -> Self { + pub fn new(analysis: Arc>, first_gas_block: u32) -> Self { Self { analysis, first_gas_block, @@ -207,17 +138,43 @@ impl ValidJumpAddress { /// Returns `true` if the position is a valid jump destination. If /// not, returns `false`. - pub fn is_valid(&self, position: usize) -> bool { if position >= self.analysis.len() { return false; } - - self.analysis[position].is_jump_dest() + self.analysis[position].is_jump() } pub fn gas_block(&self, position: usize) -> u64 { - self.analysis[position].gas_block + self.analysis[position].gas_block() + } +} + +#[cfg(test)] +mod tests { + use super::AnalysisData; + + #[test] + pub fn test_jump_set() { + let mut jump = AnalysisData::none(); + assert!(!jump.is_jump()); + assert_eq!(jump.gas_block(), 0); + + jump.set_gas_block(2350); + assert!(!jump.is_jump()); + assert_eq!(jump.gas_block(), 2350); + + jump.set_is_jump(); + assert!(jump.is_jump()); + assert_eq!(jump.gas_block(), 2350); + + jump.set_gas_block(10); + assert!(jump.is_jump()); + assert_eq!(jump.gas_block(), 10); + + jump.set_gas_block(350); + assert!(jump.is_jump()); + assert_eq!(jump.gas_block(), 350); } } diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index fa3ea26e30..d78721833d 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -24,7 +24,9 @@ pub use instructions::{ opcode::{self, spec_opcode_gas, OpCode, OPCODE_JUMPMAP}, Return, }; -pub use interpreter::{Contract, Interpreter, Memory, Stack}; +pub use interpreter::{ + Bytecode, BytecodeLocked, BytecodeState, Contract, Interpreter, Memory, Stack, +}; pub use models::*; pub use specification::*; pub use subroutine::{Account, Filth, SubRoutine}; diff --git a/crates/revm/src/models.rs b/crates/revm/src/models.rs index aa5be44801..0ae692c8fb 100644 --- a/crates/revm/src/models.rs +++ b/crates/revm/src/models.rs @@ -1,9 +1,8 @@ use core::cmp::min; -use crate::{alloc::vec::Vec, SpecId}; +use crate::{alloc::vec::Vec, interpreter::bytecode::Bytecode, SpecId}; use bytes::Bytes; use primitive_types::{H160, H256, U256}; -use sha3::{Digest, Keccak256}; pub const KECCAK_EMPTY: H256 = H256([ 0xc5, 0xd2, 0x46, 0x01, 0x86, 0xf7, 0x23, 0x3c, 0x92, 0x7e, 0x7d, 0xb2, 0xdc, 0xc7, 0x03, 0xc0, @@ -11,7 +10,7 @@ pub const KECCAK_EMPTY: H256 = H256([ ]); /// AccountInfo account information. -#[derive(Clone, Eq, PartialEq, Debug)] +#[derive(Clone, Debug)] #[cfg_attr(feature = "with-serde", derive(serde::Serialize, serde::Deserialize))] pub struct AccountInfo { /// Account balance. @@ -22,8 +21,7 @@ pub struct AccountInfo { pub code_hash: H256, /// code: if None, `code_by_hash` will be used to fetch it if code needs to be loaded from /// inside of revm. - #[cfg_attr(feature = "with-serde", serde(with = "serde_hex_bytes_opt"))] - pub code: Option, + pub code: Option, } impl Default for AccountInfo { @@ -31,19 +29,15 @@ impl Default for AccountInfo { Self { balance: U256::zero(), code_hash: KECCAK_EMPTY, - code: Some(Bytes::new()), + code: Some(Bytecode::new()), nonce: 0, } } } impl AccountInfo { - pub fn new(balance: U256, nonce: u64, code: Bytes) -> Self { - let code_hash = if code.is_empty() { - KECCAK_EMPTY - } else { - H256::from_slice(Keccak256::digest(&code).as_slice()) - }; + pub fn new(balance: U256, nonce: u64, code: Bytecode) -> Self { + let code_hash = code.hash(); Self { balance, nonce, @@ -316,10 +310,9 @@ pub struct SelfDestructResult { pub is_cold: bool, pub previously_destroyed: bool, } - /// Serde functions to serde as [bytes::Bytes] hex string #[cfg(feature = "with-serde")] -mod serde_hex_bytes { +pub(crate) mod serde_hex_bytes { use serde::{Deserialize, Deserializer, Serializer}; pub fn serialize(x: T, s: S) -> Result @@ -346,7 +339,7 @@ mod serde_hex_bytes { } /// Serde functions to serde an Option [bytes::Bytes] hex string #[cfg(feature = "with-serde")] -mod serde_hex_bytes_opt { +pub(crate) mod serde_hex_bytes_opt { use super::serde_hex_bytes; use serde::{Deserialize, Deserializer, Serializer}; diff --git a/crates/revm/src/specification.rs b/crates/revm/src/specification.rs index 41dd094326..5f817e5956 100644 --- a/crates/revm/src/specification.rs +++ b/crates/revm/src/specification.rs @@ -18,7 +18,8 @@ pub enum SpecId { MUIRGLACIER = 9, BERLIN = 10, LONDON = 11, - LATEST = 12, + MERGE = 12, + LATEST = 13, } impl SpecId { @@ -27,7 +28,7 @@ impl SpecId { FRONTIER | HOMESTEAD | TANGERINE | SPURIOUS_DRAGON => PrecompileId::HOMESTEAD as u8, BYZANTIUM | CONSTANTINOPLE | PETERSBURG => PrecompileId::BYZANTIUM as u8, ISTANBUL | MUIRGLACIER => PrecompileId::ISTANBUL as u8, - BERLIN | LONDON | LATEST => PrecompileId::BERLIN as u8, + BERLIN | LONDON | MERGE | LATEST => PrecompileId::BERLIN as u8, } } @@ -52,6 +53,7 @@ impl From<&str> for SpecId { "MuirGlacier" => SpecId::MUIRGLACIER, "Berlin" => SpecId::BERLIN, "London" => SpecId::LONDON, + "Merge" => SpecId::MERGE, _ => SpecId::LATEST, } } @@ -81,7 +83,7 @@ pub trait Spec: Sized { const ASSUME_PRECOMPILE_HAS_BALANCE: bool; } -mod spec_impl { +pub(crate) mod spec_impl { use super::{NotStaticSpec, Spec}; macro_rules! spec { @@ -118,6 +120,7 @@ mod spec_impl { } spec!(LATEST); + spec!(MERGE); spec!(LONDON); spec!(BERLIN); spec!(ISTANBUL); @@ -128,5 +131,5 @@ mod spec_impl { pub use spec_impl::{ BERLIN::SpecImpl as BerlinSpec, BYZANTIUM::SpecImpl as ByzantiumSpec, FRONTIER::SpecImpl as FrontierSpec, ISTANBUL::SpecImpl as IstanbulSpec, - LATEST::SpecImpl as LatestSpec, LONDON::SpecImpl as LondonSpec, + LATEST::SpecImpl as LatestSpec, LONDON::SpecImpl as LondonSpec, MERGE::SpecImpl as MergeSpec, }; diff --git a/crates/revm/src/subroutine.rs b/crates/revm/src/subroutine.rs index 187cbc79e1..1590955030 100644 --- a/crates/revm/src/subroutine.rs +++ b/crates/revm/src/subroutine.rs @@ -1,9 +1,7 @@ -use crate::{models::SelfDestructResult, Return, KECCAK_EMPTY}; +use crate::{interpreter::bytecode::Bytecode, models::SelfDestructResult, Return, KECCAK_EMPTY}; use alloc::{vec, vec::Vec}; use core::mem::{self}; use hashbrown::{hash_map::Entry, HashMap as Map}; - -use bytes::Bytes; use primitive_types::{H160, H256, U256}; use crate::{db::Database, AccountInfo, Log}; @@ -168,7 +166,7 @@ impl SubRoutine { } /// use it only if you know that acc is hot - pub fn set_code(&mut self, address: H160, code: Bytes, code_hash: H256) { + pub fn set_code(&mut self, address: H160, code: Bytecode, code_hash: H256) { let acc = self.log_dirty(address, |_| {}); acc.info.code = Some(code); acc.info.code_hash = code_hash; @@ -330,7 +328,7 @@ impl SubRoutine { } ChangeLog::Created(balance, orig_filth) => { let acc = state.get_mut(&add).unwrap(); - acc.info.code = Some(Bytes::new()); + acc.info.code = Some(Bytecode::new()); acc.info.code_hash = KECCAK_EMPTY; acc.info.nonce = 0; acc.info.balance = balance; @@ -518,7 +516,7 @@ impl SubRoutine { ); if acc.info.code.is_none() { let code = if dont_load_from_db { - Bytes::new() + Bytecode::new() } else { db.code_by_hash(acc.info.code_hash) }; diff --git a/crates/revmjs/src/lib.rs b/crates/revmjs/src/lib.rs index f8e9906c71..a4f6302b11 100644 --- a/crates/revmjs/src/lib.rs +++ b/crates/revmjs/src/lib.rs @@ -1,9 +1,9 @@ use core::convert::TryInto; use bn_rs::BN; -use bytes::{Bytes, BytesMut}; +use bytes::Bytes; use primitive_types::{H160, U256}; -use revm::{AccountInfo, DatabaseCommit, InMemoryDB, SpecId, TransactTo, EVM as rEVM}; +use revm::{AccountInfo, Bytecode, DatabaseCommit, InMemoryDB, SpecId, TransactTo, EVM as rEVM}; use wasm_bindgen::prelude::*; #[wasm_bindgen] @@ -64,7 +64,7 @@ impl EVM { let acc_info = AccountInfo::new( balance.try_into().unwrap(), nonce, - Bytes::copy_from_slice(code), + Bytecode::new_raw(Bytes::copy_from_slice(code)), ); console_log!("Added account:{:?} info:{:?}", address, acc_info); self.revm @@ -127,7 +127,7 @@ impl EVM { self.revm.env.tx.nonce = nonce; } pub fn tx_data(&mut self, data: &[u8]) { - self.revm.env.tx.data = BytesMut::from(data).freeze(); + self.revm.env.tx.data = data.to_vec().into(); } pub fn tx_transact_to_create(&mut self) { self.revm.env.tx.transact_to = TransactTo::create();