diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 452de90c..ce728a7c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,16 +32,20 @@ jobs: - uses: Swatinem/rust-cache@v2 - run: cargo test --workspace ${{ matrix.flags }} -# test-no-std: -# name: test no_std -# runs-on: ubuntu-latest -# timeout-minutes: 30 -# steps: -# - uses: actions/checkout@v4 -# - uses: dtolnay/rust-toolchain@stable -# with: -# targets: riscv32imac-unknown-none-elf -# - run: cargo check --target riscv32imac-unknown-none-elf --no-default-features +# check-no-std: +# name: check no_std ${{ matrix.features }} +# runs-on: ubuntu-latest +# timeout-minutes: 30 +# strategy: +# fail-fast: false +# matrix: +# features: ["", "optimism"] +# steps: +# - uses: actions/checkout@v4 +# - uses: dtolnay/rust-toolchain@stable +# with: +# targets: riscv32imac-unknown-none-elf +# - run: cargo check --target riscv32imac-unknown-none-elf --no-default-features --features=${{ matrix.features }} check: name: check ${{ matrix.features }} @@ -53,9 +57,8 @@ jobs: features: ["", "serde", "std"] steps: - uses: actions/checkout@v4 - - run: | - cd crates/revm - cargo check --no-default-features --features=${{ matrix.features }} + - uses: dtolnay/rust-toolchain@stable + - run: cargo check --no-default-features -p revm --features=${{ matrix.features }} clippy: name: clippy / ${{ matrix.network }} diff --git a/Cargo.lock b/Cargo.lock index 1b868708..6541b5d3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -46,9 +46,9 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy-chains" -version = "0.1.21" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd47e5f8545bdf53beb545d3c039b4afa16040bdf69c50100581579b08776afd" +checksum = "d2feb5f466b3a786d5a622d8926418bc6a0d38bf632909f6ee9298a4a1d8c6e0" dependencies = [ "num_enum", "strum", @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cc7579e4fb5558af44810f542c90d1145dba8b92c08211c215196160c48d2ea" +checksum = "3f63a6c9eb45684a5468536bc55379a2af0f45ffa5d756e4e4964532737e1836" dependencies = [ "alloy-eips", "alloy-primitives", @@ -70,24 +70,27 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdbc8d98cc36ebe17bb5b42d0873137bc76628a4ee0f7e7acad5b8fc59d3597" +checksum = "aa4b0fc6a572ef2eebda0a31a5e393d451abda703fec917c75d9615d8c978cf2" dependencies = [ "alloy-primitives", "alloy-rlp", "alloy-serde", + "arbitrary", "c-kzg", "once_cell", + "proptest", + "proptest-derive", "serde", "sha2 0.10.8", ] [[package]] name = "alloy-json-rpc" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d06d33b79246313c4103ef9596c721674a926f1ddc8b605aa2bac4d8ba94ee34" +checksum = "d484c2a934d0a4d86f8ad4db8113cb1d607707a6c54f6e78f4f1b4451b47aa70" dependencies = [ "alloy-primitives", "serde", @@ -98,9 +101,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef742b478a2db5c27063cde82128dfbecffcd38237d7f682a91d3ecf6aa1836c" +checksum = "7a20eba9bc551037f0626d6d29e191888638d979943fa4e842e9e6fc72bf0565" dependencies = [ "alloy-consensus", "alloy-eips", @@ -145,9 +148,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200b786259a17acf318b9c423afe9669bec24ce9cdf59de153ff9a4009914bb6" +checksum = "ad5d89acb7339fad13bc69e7b925232f242835bfd91c82fcb9326b36481bd0f0" dependencies = [ "alloy-chains", "alloy-consensus", @@ -177,9 +180,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b155716bab55763c95ba212806cf43d05bcc70e5f35b02bad20cf5ec7fe11fed" +checksum = "a43b18702501396fa9bcdeecd533bc85fac75150d308fc0f6800a01e6234a003" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -188,9 +191,9 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8037e03c7f462a063f28daec9fda285a9a89da003c552f8637a80b9c8fd96241" +checksum = "d83524c1f6162fcb5b0decf775498a125066c86dda6066ed609531b0e912f85a" dependencies = [ "proc-macro2", "quote", @@ -199,9 +202,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "328a6a14aba6152ddf6d01bac5e17a70dbe9d6f343bf402b995c30bac63a1fbf" +checksum = "479ce003e8c74bbbc7d4235131c1d6b7eaf14a533ae850295b90d240340989cb" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -220,9 +223,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bce0676f144be1eae71122d1d417885a3b063add0353b35e46cdf1440d6b33b1" +checksum = "13bd7aa9ff9e67f1ba7ee0dd8cebfc95831d1649b0e4eeefae940dc3681079fa" dependencies = [ "alloy-consensus", "alloy-eips", @@ -238,20 +241,23 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c224916316519558d8c2b6a60dc7626688c08f1b8951774702562dbcb8666ee" +checksum = "8913f9e825068d77c516188c221c44f78fd814fce8effe550a783295a2757d19" dependencies = [ "alloy-primitives", + "arbitrary", + "proptest", + "proptest-derive", "serde", "serde_json", ] [[package]] name = "alloy-signer" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227c5fd0ed6e06e1ccc30593f8ff6d9fb907ac5f03a709a6d687f0943494a229" +checksum = "f740e13eb4c6a0e4d0e49738f1e86f31ad2d7ef93be499539f492805000f7237" dependencies = [ "alloy-primitives", "async-trait", @@ -322,9 +328,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3628d81530263fe837a09cd527022f5728202a669973f04270942f4d390b5f5" +checksum = "dd9773e4ec6832346171605c776315544bd06e40f803e7b5b7824b325d5442ca" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -340,9 +346,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f35d34e7a51503c9ff267404a5850bd58f991b7ab524b892f364901e3576376" +checksum = "ff8ef947b901c0d4e97370f9fa25844cf8b63b1a58fd4011ee82342dc8a9fc6b" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -409,6 +415,9 @@ name = "arbitrary" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +dependencies = [ + "derive_arbitrary", +] [[package]] name = "ark-bls12-381" @@ -684,9 +693,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -931,9 +940,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -1000,18 +1009,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstyle", "clap_lex", @@ -1019,9 +1028,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "cometbft" @@ -1164,9 +1173,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.11.4" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ff96486ccc291d36a958107caf2c0af8c78c0af7d31ae2f35ce055130de1a6" +checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" dependencies = [ "cfg-if", "cpufeatures", @@ -1238,7 +1247,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.4", + "clap 4.5.7", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -1434,15 +1443,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -1475,6 +1484,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "dunce" version = "1.0.4" @@ -1713,9 +1733,9 @@ dependencies = [ [[package]] name = "ethereum_ssz" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e61ffea29f26e8249d35128a82ec8d3bd4fbc80179ea5f5e5e3daafef6a80fcb" +checksum = "7d3627f83d8b87b432a5fad9934b4565260722a141a2c40f371f8080adec9425" dependencies = [ "ethereum-types", "itertools 0.10.5", @@ -1832,7 +1852,7 @@ dependencies = [ "proc-macro2", "quote", "syn 1.0.109", - "synstructure", + "synstructure 0.12.6", ] [[package]] @@ -2103,9 +2123,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "glob" @@ -2245,12 +2265,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -2379,9 +2393,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" [[package]] name = "httpdate" @@ -2391,9 +2405,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes 1.6.0", "futures-channel", @@ -2441,7 +2455,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.29", "rustls", "tokio", "tokio-rustls", @@ -2521,14 +2535,134 @@ dependencies = [ "sha3 0.8.2", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -2651,15 +2785,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.13.0" @@ -2770,6 +2895,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -2797,9 +2928,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "microbench" @@ -2991,9 +3122,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.2" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -3429,9 +3560,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -3531,7 +3662,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.66", @@ -3685,9 +3816,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ "bitflags 2.5.0", ] @@ -3700,7 +3831,7 @@ checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", + "regex-automata 0.4.7", "regex-syntax", ] @@ -3712,9 +3843,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -3723,9 +3854,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "relative-path" @@ -3747,7 +3878,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.29", "hyper-rustls", "ipnet", "js-sys", @@ -3819,7 +3950,7 @@ dependencies = [ [[package]] name = "revm" -version = "10.0.0" +version = "11.0.0" dependencies = [ "alloy-eips", "alloy-provider", @@ -3845,7 +3976,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "6.0.0" +version = "7.0.0" dependencies = [ "bincode", "paste", @@ -3858,14 +3989,14 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "8.0.0" +version = "9.0.0" dependencies = [ - "alloy-primitives", "alloy-rlp", "aurora-engine-modexp", "bls_on_arkworks", "blst", "c-kzg", + "cfg-if", "cometbft", "cometbft-light-client", "cometbft-light-client-verifier", @@ -3892,8 +4023,9 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "5.0.0" +version = "6.0.0" dependencies = [ + "alloy-eips", "alloy-primitives", "auto_impl", "bitflags 2.5.0", @@ -3925,7 +4057,7 @@ dependencies = [ [[package]] name = "revme" -version = "0.6.0" +version = "0.7.0" dependencies = [ "alloy-rlp", "hash-db", @@ -4385,9 +4517,9 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +checksum = "387cc504cb06bb40a96c8e04e951fe01854cf6bc921053c954e4a606d9675c6a" dependencies = [ "serde", ] @@ -4622,6 +4754,12 @@ dependencies = [ "der 0.7.9", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -4669,11 +4807,11 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", @@ -4766,6 +4904,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -4943,30 +5092,25 @@ dependencies = [ ] [[package]] -name = "tinytemplate" -version = "1.2.1" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "serde", - "serde_json", + "displaydoc", + "zerovec", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinytemplate" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ - "tinyvec_macros", + "serde", + "serde_json", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.38.0" @@ -5073,7 +5217,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.14", + "toml_edit 0.22.15", ] [[package]] @@ -5098,15 +5242,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.11", + "winnow 0.6.13", ] [[package]] @@ -5246,27 +5390,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-segmentation" version = "1.11.0" @@ -5275,9 +5404,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -5299,9 +5428,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", "idna", @@ -5314,11 +5443,23 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "uuid" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" [[package]] name = "valuable" @@ -5656,9 +5797,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.11" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c52728401e1dc672a56e81e593e912aa54c78f40246869f78359a2bf24d29d" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" dependencies = [ "memchr", ] @@ -5683,6 +5824,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "ws_stream_wasm" version = "0.7.4" @@ -5717,6 +5870,30 @@ dependencies = [ "tap", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure 0.13.1", +] + [[package]] name = "zerocopy" version = "0.7.34" @@ -5737,11 +5914,32 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure 0.13.1", +] + [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -5756,3 +5954,25 @@ dependencies = [ "quote", "syn 2.0.66", ] + +[[package]] +name = "zerovec" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] diff --git a/Cargo.toml b/Cargo.toml index 426d6e40..ad5a6ccd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,3 +22,8 @@ debug = true [profile.ethtests] inherits = "test" opt-level = 3 + +# [patch.crates-io] +# alloy-eips = { git = "https://github.com/alloy-rs/alloy.git", rev = "41d4c7c" } +# alloy-provider = { git = "https://github.com/alloy-rs/alloy.git", rev = "41d4c7c" } +# alloy-transport = { git = "https://github.com/alloy-rs/alloy.git", rev = "41d4c7c" } \ No newline at end of file diff --git a/README.md b/README.md index 254952bb..83b93424 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,7 @@ cargo run -p revm --features std,serde-json,ethersdb --example generate_block_tr * [Hardhat](https://github.com/NomicFoundation/hardhat) is a development environment to compile, deploy, test, and debug your Ethereum software. * [Trin](https://github.com/ethereum/trin) is Portal Network client. An execution and consensus layer Ethereum light client written in Rust. Portal Network client's provide complete, provable, and distributed execution archival access. * [Simular](https://github.com/simular-fi/simular/) is a Python smart-contract API with a fast, embedded, Ethereum Virtual Machine. +* [rbuilder](https://github.com/flashbots/rbuilder) is a state of the art Ethereum MEV-Boost block builder written in Rust and designed to work with Reth. * ... (If you want to add project to the list, ping me or open the PR) diff --git a/bins/revm-test/CHANGELOG.md b/bins/revm-test/CHANGELOG.md index 63053a34..d8b7c02c 100644 --- a/bins/revm-test/CHANGELOG.md +++ b/bins/revm-test/CHANGELOG.md @@ -6,6 +6,97 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.1.0](https://github.com/bluealloy/revm/releases/tag/revm-test-v0.1.0) - 2024-07-08 + +### Added +- EOF (Ethereum Object Format) ([#1143](https://github.com/bluealloy/revm/pull/1143)) +- add tests for shift instructions ([#1254](https://github.com/bluealloy/revm/pull/1254)) +- EvmBuilder and External Contexts ([#888](https://github.com/bluealloy/revm/pull/888)) +- separate initial checks ([#486](https://github.com/bluealloy/revm/pull/486)) +- revm-interpreter created ([#320](https://github.com/bluealloy/revm/pull/320)) +- *(interpreter)* Unify instruction fn signature ([#283](https://github.com/bluealloy/revm/pull/283)) +- Migrate `primitive_types::U256` to `ruint::Uint<256, 4>` ([#239](https://github.com/bluealloy/revm/pull/239)) +- Introduce ByteCode format, Update Readme ([#156](https://github.com/bluealloy/revm/pull/156)) + +### Fixed +- *(eof)* fixture 2 tests ([#1550](https://github.com/bluealloy/revm/pull/1550)) +- *(clippy)* fix some clippy lints + +### Other +- release ([#1548](https://github.com/bluealloy/revm/pull/1548)) +- replace TransactTo with TxKind ([#1542](https://github.com/bluealloy/revm/pull/1542)) +- *(deps)* bump regex from 1.10.4 to 1.10.5 ([#1502](https://github.com/bluealloy/revm/pull/1502)) +- release ([#1261](https://github.com/bluealloy/revm/pull/1261)) +- *(interpreter)* rewrite gas accounting for memory expansion ([#1361](https://github.com/bluealloy/revm/pull/1361)) +- revert snailtracer without microbench ([#1259](https://github.com/bluealloy/revm/pull/1259)) +- release ([#1231](https://github.com/bluealloy/revm/pull/1231)) +- *(deps)* bump other alloy deps 0.7.0 ([#1252](https://github.com/bluealloy/revm/pull/1252)) +- *(deps)* bump regex from 1.10.3 to 1.10.4 ([#1223](https://github.com/bluealloy/revm/pull/1223)) +- *(deps)* bump bytes from 1.5.0 to 1.6.0 ([#1224](https://github.com/bluealloy/revm/pull/1224)) +- release ([#1175](https://github.com/bluealloy/revm/pull/1175)) +- tag v32 revm v7.1.0 ([#1176](https://github.com/bluealloy/revm/pull/1176)) +- release ([#1125](https://github.com/bluealloy/revm/pull/1125)) +- *(deps)* bump alloy-sol-types from 0.6.3 to 0.6.4 ([#1148](https://github.com/bluealloy/revm/pull/1148)) +- *(deps)* bump alloy-sol-macro from 0.6.3 to 0.6.4 ([#1136](https://github.com/bluealloy/revm/pull/1136)) +- release tag v30 revm v6.1.0 ([#1100](https://github.com/bluealloy/revm/pull/1100)) +- clippy cleanup ([#1112](https://github.com/bluealloy/revm/pull/1112)) +- *(deps)* bump alloy-sol-types from 0.6.2 to 0.6.3 ([#1103](https://github.com/bluealloy/revm/pull/1103)) +- release ([#1082](https://github.com/bluealloy/revm/pull/1082)) +- *(deps)* bump alloy-sol-macro from 0.6.2 to 0.6.3 ([#1094](https://github.com/bluealloy/revm/pull/1094)) +- license date and revm docs ([#1080](https://github.com/bluealloy/revm/pull/1080)) +- release ([#1067](https://github.com/bluealloy/revm/pull/1067)) +- tag v27, revm v4.0.0 release ([#1061](https://github.com/bluealloy/revm/pull/1061)) +- *(deps)* bump eyre from 0.6.11 to 0.6.12 ([#1051](https://github.com/bluealloy/revm/pull/1051)) +- *(deps)* bump alloy-sol-types from 0.6.0 to 0.6.2 ([#1035](https://github.com/bluealloy/revm/pull/1035)) +- *(deps)* bump alloy-sol-macro from 0.6.0 to 0.6.2 ([#1013](https://github.com/bluealloy/revm/pull/1013)) +- chore(Test) : const to static ([#1016](https://github.com/bluealloy/revm/pull/1016)) +- Burntpix criterion bench ([#1004](https://github.com/bluealloy/revm/pull/1004)) +- Instruction table ([#759](https://github.com/bluealloy/revm/pull/759)) +- rewrite revm-test as a criterion bench ([#579](https://github.com/bluealloy/revm/pull/579)) +- optimize stack usage for recursive `call` and `create` programs ([#522](https://github.com/bluealloy/revm/pull/522)) +- Bump v24, revm v3.3.0 ([#476](https://github.com/bluealloy/revm/pull/476)) +- Release v23, revm v3.2.0 ([#464](https://github.com/bluealloy/revm/pull/464)) +- Release v22, revm v3.1.1 ([#460](https://github.com/bluealloy/revm/pull/460)) +- v21, revm v3.1.0 ([#444](https://github.com/bluealloy/revm/pull/444)) +- remove gas blocks ([#391](https://github.com/bluealloy/revm/pull/391)) +- *(deps)* bump bytes from 1.3.0 to 1.4.0 ([#355](https://github.com/bluealloy/revm/pull/355)) +- Bump v20, changelog ([#350](https://github.com/bluealloy/revm/pull/350)) +- includes to libs ([#338](https://github.com/bluealloy/revm/pull/338)) +- Creating revm-primitives, revm better errors and db components ([#334](https://github.com/bluealloy/revm/pull/334)) +- Cleanup, move hot fields toggether in Interpreter ([#321](https://github.com/bluealloy/revm/pull/321)) +- native bits ([#278](https://github.com/bluealloy/revm/pull/278)) +- *(release)* Bump revm and precompiles versions +- Bump primitive_types. Add statetest spec +- Bump revm v2.1.0 ([#224](https://github.com/bluealloy/revm/pull/224)) +- revm bump v2.0.0, precompile bump v1.1.1 ([#212](https://github.com/bluealloy/revm/pull/212)) +- Cfg choose create analysis, option on bytecode size limit ([#210](https://github.com/bluealloy/revm/pull/210)) +- Cargo sort. Bump lib versions ([#208](https://github.com/bluealloy/revm/pull/208)) +- Return `ExecutionResult`, which includes `gas_refunded` ([#169](https://github.com/bluealloy/revm/pull/169)) +- Bytecode hash, remove override_spec, ([#165](https://github.com/bluealloy/revm/pull/165)) +- revm bump 1.8. update libs. snailtracer rename ([#159](https://github.com/bluealloy/revm/pull/159)) +- v6 changelog, bump versions +- Big Refactor. Machine to Interpreter. refactor instructions. call/create struct ([#52](https://github.com/bluealloy/revm/pull/52)) +- [revm] pop_top and unsafe comments ([#51](https://github.com/bluealloy/revm/pull/51)) +- [precompiles] remove unused borsh +- [recompl] Bump precompile deps, cargo sort on workspace +- [revm] output log. Stetetest test log output. fmt +- Bump versions, Changelogs, fmt, revm readme, clippy. +- [revm] Run test multiple times. fmt, BenchmarkDB +- Multiple changes: web3 db, debugger initial commit, precompile load +- Memory to usize, clippy,fmt +- wip optimize i256 +- TEMP switch stacks H256 with U256 +- [revm] some perfs +- [revm] Perfs stack pop. Benchmark snailtracer. +- [revm] cleanup +- fmt +- EVM Interface changed. Inspector called separately +- Bump revm v0.3.0. README updated +- DB ref mut polished +- And now we debug +- [revm] Interface. Inspector added, Env cleanup. revm-test passes +- Rename bin to bins + ## [0.1.0](https://github.com/bluealloy/revm/releases/tag/revm-test-v0.1.0) - 2024-06-20 ### Added diff --git a/bins/revm-test/Cargo.toml b/bins/revm-test/Cargo.toml index c18da113..af0b895b 100644 --- a/bins/revm-test/Cargo.toml +++ b/bins/revm-test/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] bytes = "1.6" hex = "0.4" -revm = { path = "../../crates/revm", version = "10.0.0", default-features=false } +revm = { path = "../../crates/revm", version = "11.0.0", default-features=false } microbench = "0.5" alloy-sol-macro = "0.7.0" alloy-sol-types = "0.7.0" diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index fdd65001..3d7a6135 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -6,6 +6,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.7.0](https://github.com/bluealloy/revm/compare/revme-v0.6.0...revme-v0.7.0) - 2024-07-08 + +### Other +- replace AccessList with alloy version ([#1552](https://github.com/bluealloy/revm/pull/1552)) + ## [0.6.0](https://github.com/bluealloy/revm/compare/revme-v0.5.0...revme-v0.6.0) - 2024-06-20 ### Added diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 04f9b264..837b8b9b 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["ethereum", "evm"] license = "MIT" repository = "https://github.com/bluealloy/revm" description = "Rust Ethereum Virtual Machine Executable" -version = "0.6.0" +version = "0.7.0" [dependencies] hash-db = "0.15" @@ -15,7 +15,7 @@ hashbrown = "0.14" indicatif = "0.17" microbench = "0.5" plain_hasher = "0.2" -revm = { path = "../../crates/revm", version = "10.0.0", default-features = false, features = [ +revm = { path = "../../crates/revm", version = "11.0.0", default-features = false, features = [ "ethersdb", "std", "serde-json", diff --git a/bins/revme/src/cmd/statetest/models/mod.rs b/bins/revme/src/cmd/statetest/models/mod.rs index 0225daac..ad409f01 100644 --- a/bins/revme/src/cmd/statetest/models/mod.rs +++ b/bins/revme/src/cmd/statetest/models/mod.rs @@ -1,4 +1,4 @@ -use revm::primitives::{Address, Bytes, HashMap, B256, U256}; +use revm::primitives::{AccessList, Address, Bytes, HashMap, B256, U256}; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -110,15 +110,6 @@ pub struct TransactionParts { pub max_fee_per_blob_gas: Option, } -#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Clone)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -pub struct AccessListItem { - pub address: Address, - pub storage_keys: Vec, -} - -pub type AccessList = Vec; - #[cfg(test)] mod tests { diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 31081a1a..3fd19cb1 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -10,7 +10,7 @@ use revm::{ inspectors::TracerEip3155, primitives::{ calc_excess_blob_gas, keccak256, Bytecode, Bytes, EVMResultGeneric, Env, Eof, - ExecutionResult, SpecId, TxKind, B256, EOF_MAGIC_BYTES, U256, + ExecutionResult, SpecId, TxKind, B256, EOF_MAGIC_BYTES, }, Evm, State, }; @@ -351,18 +351,8 @@ pub fn execute_test_suite( .access_lists .get(test.indexes.data) .and_then(Option::as_deref) - .unwrap_or_default() - .iter() - .map(|item| { - ( - item.address, - item.storage_keys - .iter() - .map(|key| U256::from_be_bytes(key.0)) - .collect::>(), - ) - }) - .collect(); + .cloned() + .unwrap_or_default(); let to = match unit.transaction.to { Some(add) => TxKind::Call(add), diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 2ae9a3ca..cc5d1e94 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -6,6 +6,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [7.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v6.0.0...revm-interpreter-v7.0.0) - 2024-07-08 + +### Added +- *(Precompiles)* Throw fatal error if c-kzg is disabled ([#1589](https://github.com/bluealloy/revm/pull/1589)) +- add bytecode_address from CallInputs to Contract during construction. ([#1568](https://github.com/bluealloy/revm/pull/1568)) +- support selfdestruct for dummyhost ([#1578](https://github.com/bluealloy/revm/pull/1578)) +- *(Prague)* Add EIP-7702 ([#1565](https://github.com/bluealloy/revm/pull/1565)) +- *(EOF)* disallow ExtDelegateCall to legacy bytecode ([#1572](https://github.com/bluealloy/revm/pull/1572)) +- *(EOF)* Add target address expansion checks ([#1570](https://github.com/bluealloy/revm/pull/1570)) + +### Fixed +- *(eof)* ExtDelegateCall caller/target switch ([#1571](https://github.com/bluealloy/revm/pull/1571)) + +### Other +- *(README)* add rbuilder to used-by ([#1585](https://github.com/bluealloy/revm/pull/1585)) +- use const blocks ([#1522](https://github.com/bluealloy/revm/pull/1522)) +- fix compile for alloydb ([#1559](https://github.com/bluealloy/revm/pull/1559)) +- replace AccessList with alloy version ([#1552](https://github.com/bluealloy/revm/pull/1552)) +- replace U256 with u64 in BLOCKHASH ([#1505](https://github.com/bluealloy/revm/pull/1505)) + ## [6.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v5.0.0...revm-interpreter-v6.0.0) - 2024-06-20 ### Added diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 8e10aeee..884607d8 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["no_std", "ethereum", "evm", "revm", "interpreter"] license = "MIT" name = "revm-interpreter" repository = "https://github.com/bluealloy/revm" -version = "6.0.0" +version = "7.0.0" readme = "../../README.md" [package.metadata.docs.rs] @@ -22,7 +22,7 @@ rust_2018_idioms = "deny" all = "warn" [dependencies] -revm-primitives = { path = "../primitives", version = "5.0.0", default-features = false } +revm-primitives = { path = "../primitives", version = "6.0.0", default-features = false } paste = { version = "1.0", optional = true } phf = { version = "0.11", default-features = false, optional = true, features = [ diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index dd434fcd..4d8aba4d 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -1,10 +1,9 @@ use super::constants::*; use crate::{ num_words, - primitives::{Address, SpecId, U256}, + primitives::{AccessListItem, SpecId, U256}, SelfDestructResult, }; -use std::vec::Vec; /// `const` Option `?`. macro_rules! tri { @@ -357,7 +356,8 @@ pub fn validate_initial_tx_gas( spec_id: SpecId, input: &[u8], is_create: bool, - access_list: &[(Address, Vec)], + access_list: &[AccessListItem], + authorization_list_num: u64, ) -> u64 { let mut initial_gas = 0; let zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; @@ -375,11 +375,9 @@ pub fn validate_initial_tx_gas( // get number of access list account and storages. if spec_id.is_enabled_in(SpecId::BERLIN) { - let accessed_slots = access_list - .iter() - .fold(0, |slot_count, (_, slots)| slot_count + slots.len() as u64); + let accessed_slots: usize = access_list.iter().map(|item| item.storage_keys.len()).sum(); initial_gas += access_list.len() as u64 * ACCESS_LIST_ADDRESS; - initial_gas += accessed_slots * ACCESS_LIST_STORAGE_KEY; + initial_gas += accessed_slots as u64 * ACCESS_LIST_STORAGE_KEY; } // base stipend @@ -400,5 +398,10 @@ pub fn validate_initial_tx_gas( initial_gas += initcode_cost(input.len() as u64) } + // EIP-7702 + if spec_id.is_enabled_in(SpecId::PRAGUE) { + initial_gas += authorization_list_num * PER_CONTRACT_CODE_BASE_COST; + } + initial_gas } diff --git a/crates/interpreter/src/gas/constants.rs b/crates/interpreter/src/gas/constants.rs index 7d7956a4..c32abcfa 100644 --- a/crates/interpreter/src/gas/constants.rs +++ b/crates/interpreter/src/gas/constants.rs @@ -47,6 +47,9 @@ pub const COLD_ACCOUNT_ACCESS_COST: u64 = 2600; pub const WARM_STORAGE_READ_COST: u64 = 100; pub const WARM_SSTORE_RESET: u64 = SSTORE_RESET - COLD_SLOAD_COST; +/// EIP-7702 +pub const PER_CONTRACT_CODE_BASE_COST: u64 = 2400; + /// EIP-3860 : Limit and meter initcode pub const INITCODE_WORD_COST: u64 = 2; diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index b432209b..e07cb316 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -17,7 +17,7 @@ pub trait Host { fn load_account(&mut self, address: Address) -> Option; /// Get the block hash of the given block `number`. - fn block_hash(&mut self, number: U256) -> Option; + fn block_hash(&mut self, number: u64) -> Option; /// Get balance of `address` and if the account is cold. fn balance(&mut self, address: Address) -> Option<(U256, bool)>; diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index 47320b08..dba50209 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -50,7 +50,7 @@ impl Host for DummyHost { } #[inline] - fn block_hash(&mut self, _number: U256) -> Option { + fn block_hash(&mut self, _number: u64) -> Option { Some(B256::ZERO) } @@ -65,12 +65,12 @@ impl Host for DummyHost { } #[inline] - fn code_hash(&mut self, __address: Address) -> Option<(B256, bool)> { + fn code_hash(&mut self, _address: Address) -> Option<(B256, bool)> { Some((KECCAK_EMPTY, false)) } #[inline] - fn sload(&mut self, __address: Address, index: U256) -> Option<(U256, bool)> { + fn sload(&mut self, _address: Address, index: U256) -> Option<(U256, bool)> { match self.storage.entry(index) { Entry::Occupied(entry) => Some((*entry.get(), false)), Entry::Vacant(entry) => { @@ -82,19 +82,12 @@ impl Host for DummyHost { #[inline] fn sstore(&mut self, _address: Address, index: U256, value: U256) -> Option { - let (present, is_cold) = match self.storage.entry(index) { - Entry::Occupied(mut entry) => (entry.insert(value), false), - Entry::Vacant(entry) => { - entry.insert(value); - (U256::ZERO, true) - } - }; - + let present = self.storage.insert(index, value); Some(SStoreResult { original_value: U256::ZERO, - present_value: present, + present_value: present.unwrap_or(U256::ZERO), new_value: value, - is_cold, + is_cold: present.is_none(), }) } @@ -118,6 +111,6 @@ impl Host for DummyHost { #[inline] fn selfdestruct(&mut self, _address: Address, _target: Address) -> Option { - panic!("Selfdestruct is not supported for this host") + Some(SelfDestructResult::default()) } } diff --git a/crates/interpreter/src/instruction_result.rs b/crates/interpreter/src/instruction_result.rs index aed0da33..47b399b5 100644 --- a/crates/interpreter/src/instruction_result.rs +++ b/crates/interpreter/src/instruction_result.rs @@ -20,6 +20,8 @@ pub enum InstructionResult { CreateInitCodeStartingEF00, /// Invalid EOF initcode, InvalidEOFInitCode, + /// ExtDelegateCall calling a non EOF contract. + InvalidExtDelegateCallTarget, // Actions CallOrCreate = 0x20, @@ -33,7 +35,7 @@ pub enum InstructionResult { OpcodeNotFound, CallNotAllowedInsideStatic, StateChangeDuringStaticCall, - InvalidEFOpcode, + InvalidFEOpcode, InvalidJump, NotActivated, StackUnderflow, @@ -59,8 +61,10 @@ pub enum InstructionResult { EOFFunctionStackOverflow, /// Aux data overflow, new aux data is larger tha u16 max size. EofAuxDataOverflow, - /// Aud data is smaller then already present data size. + /// Aux data is smaller then already present data size. EofAuxDataTooSmall, + /// EXT*CALL target address needs to be padded with 0s. + InvalidEXTCALLTarget, } impl From for InstructionResult { @@ -85,7 +89,7 @@ impl From for InstructionResult { OutOfGasError::Precompile => Self::PrecompileOOG, }, HaltReason::OpcodeNotFound => Self::OpcodeNotFound, - HaltReason::InvalidEFOpcode => Self::InvalidEFOpcode, + HaltReason::InvalidFEOpcode => Self::InvalidFEOpcode, HaltReason::InvalidJump => Self::InvalidJump, HaltReason::NotActivated => Self::NotActivated, HaltReason::StackOverflow => Self::StackOverflow, @@ -130,6 +134,7 @@ macro_rules! return_revert { | InstructionResult::OutOfFunds | InstructionResult::InvalidEOFInitCode | InstructionResult::CreateInitCodeStartingEF00 + | InstructionResult::InvalidExtDelegateCallTarget }; } @@ -144,7 +149,7 @@ macro_rules! return_error { | InstructionResult::OpcodeNotFound | InstructionResult::CallNotAllowedInsideStatic | InstructionResult::StateChangeDuringStaticCall - | InstructionResult::InvalidEFOpcode + | InstructionResult::InvalidFEOpcode | InstructionResult::InvalidJump | InstructionResult::NotActivated | InstructionResult::StackUnderflow @@ -163,6 +168,7 @@ macro_rules! return_error { | InstructionResult::EOFFunctionStackOverflow | InstructionResult::EofAuxDataTooSmall | InstructionResult::EofAuxDataOverflow + | InstructionResult::InvalidEXTCALLTarget }; } @@ -195,6 +201,10 @@ pub enum InternalResult { InternalCallOrCreate, /// Internal CREATE/CREATE starts with 0xEF00 CreateInitCodeStartingEF00, + /// Check for target address validity is only done inside subcall. + InvalidEXTCALLTarget, + /// Internal to ExtDelegateCall + InvalidExtDelegateCallTarget, } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -276,7 +286,7 @@ impl From for SuccessOrHalt { InstructionResult::StateChangeDuringStaticCall => { Self::Halt(HaltReason::StateChangeDuringStaticCall) } - InstructionResult::InvalidEFOpcode => Self::Halt(HaltReason::InvalidEFOpcode), + InstructionResult::InvalidFEOpcode => Self::Halt(HaltReason::InvalidFEOpcode), InstructionResult::InvalidJump => Self::Halt(HaltReason::InvalidJump), InstructionResult::NotActivated => Self::Halt(HaltReason::NotActivated), InstructionResult::StackUnderflow => Self::Halt(HaltReason::StackUnderflow), @@ -303,6 +313,12 @@ impl From for SuccessOrHalt { InstructionResult::ReturnContract => Self::Success(SuccessReason::EofReturnContract), InstructionResult::EofAuxDataOverflow => Self::Halt(HaltReason::EofAuxDataOverflow), InstructionResult::EofAuxDataTooSmall => Self::Halt(HaltReason::EofAuxDataTooSmall), + InstructionResult::InvalidEXTCALLTarget => { + Self::Internal(InternalResult::InvalidEXTCALLTarget) + } + InstructionResult::InvalidExtDelegateCallTarget => { + Self::Internal(InternalResult::InvalidExtDelegateCallTarget) + } } } } @@ -357,7 +373,7 @@ mod tests { InstructionResult::OpcodeNotFound, InstructionResult::CallNotAllowedInsideStatic, InstructionResult::StateChangeDuringStaticCall, - InstructionResult::InvalidEFOpcode, + InstructionResult::InvalidFEOpcode, InstructionResult::InvalidJump, InstructionResult::NotActivated, InstructionResult::StackUnderflow, diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index ea58ad40..a278a220 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -6,7 +6,7 @@ use crate::{ gas::{self, cost_per_word, EOF_CREATE_GAS, KECCAK256WORD}, interpreter::Interpreter, primitives::{ - eof::EofHeader, keccak256, Address, BerlinSpec, Bytes, Eof, Spec, SpecId::*, U256, + eof::EofHeader, keccak256, Address, BerlinSpec, Bytes, Eof, Spec, SpecId::*, B256, U256, }, CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInputs, Host, InstructionResult, InterpreterAction, InterpreterResult, LoadAccountResult, MAX_INITCODE_SIZE, @@ -195,11 +195,29 @@ pub fn extcall_gas_calc( Some(gas_limit) } +/// Pop target address from stack and check if it is valid. +/// +/// Valid address has first 12 bytes as zeroes. +#[inline] +pub fn pop_extcall_target_address(interpreter: &mut Interpreter) -> Option
{ + pop_ret!(interpreter, target_address, None); + let target_address = B256::from(target_address); + // Check if target is left padded with zeroes. + if target_address[..12].iter().any(|i| *i != 0) { + interpreter.instruction_result = InstructionResult::InvalidEXTCALLTarget; + return None; + } + // discard first 12 bytes. + Some(Address::from_word(target_address)) +} + pub fn extcall(interpreter: &mut Interpreter, host: &mut H) { require_eof!(interpreter); - pop_address!(interpreter, target_address); - // TODO check if target is left paddded with zeroes. + // pop target address + let Some(target_address) = pop_extcall_target_address(interpreter) else { + return; + }; // input call let Some(input) = extcall_input(interpreter) else { @@ -223,7 +241,7 @@ pub fn extcall(interpreter: &mut Interpreter, host caller: interpreter.contract.target_address, bytecode_address: target_address, value: CallValue::Transfer(value), - scheme: CallScheme::Call, + scheme: CallScheme::ExtCall, is_static: interpreter.is_static, is_eof: true, return_memory_offset: 0..0, @@ -234,9 +252,11 @@ pub fn extcall(interpreter: &mut Interpreter, host pub fn extdelegatecall(interpreter: &mut Interpreter, host: &mut H) { require_eof!(interpreter); - pop_address!(interpreter, target_address); - // TODO check if target is left paddded with zeroes. + // pop target address + let Some(target_address) = pop_extcall_target_address(interpreter) else { + return; + }; // input call let Some(input) = extcall_input(interpreter) else { @@ -253,12 +273,11 @@ pub fn extdelegatecall(interpreter: &mut Interpret inputs: Box::new(CallInputs { input, gas_limit, - target_address, - caller: interpreter.contract.target_address, + target_address: interpreter.contract.target_address, + caller: interpreter.contract.caller, bytecode_address: target_address, value: CallValue::Apparent(interpreter.contract.call_value), - // TODO(EOF) should be EofDelegateCall? - scheme: CallScheme::DelegateCall, + scheme: CallScheme::ExtDelegateCall, is_static: interpreter.is_static, is_eof: true, return_memory_offset: 0..0, @@ -269,9 +288,11 @@ pub fn extdelegatecall(interpreter: &mut Interpret pub fn extstaticcall(interpreter: &mut Interpreter, host: &mut H) { require_eof!(interpreter); - pop_address!(interpreter, target_address); - // TODO check if target is left paddded with zeroes. + // pop target address + let Some(target_address) = pop_extcall_target_address(interpreter) else { + return; + }; // input call let Some(input) = extcall_input(interpreter) else { @@ -291,7 +312,7 @@ pub fn extstaticcall(interpreter: &mut Interpreter, host: &mut caller: interpreter.contract.target_address, bytecode_address: target_address, value: CallValue::Transfer(U256::ZERO), - scheme: CallScheme::Call, + scheme: CallScheme::ExtStaticCall, is_static: true, is_eof: true, return_memory_offset: 0..0, diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index 3bf4e435..4aacffd9 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -194,7 +194,7 @@ pub fn stop(interpreter: &mut Interpreter, _host: &mut H) { /// Invalid opcode. This opcode halts the execution. pub fn invalid(interpreter: &mut Interpreter, _host: &mut H) { - interpreter.instruction_result = InstructionResult::InvalidEFOpcode; + interpreter.instruction_result = InstructionResult::InvalidFEOpcode; } /// Unknown opcode. This opcode halts the execution. diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index a25f5148..8992c6c1 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -106,7 +106,8 @@ pub fn blockhash(interpreter: &mut Interpreter, ho gas!(interpreter, gas::BLOCKHASH); pop_top!(interpreter, number); - let Some(hash) = host.block_hash(*number) else { + let number_u64 = as_u64_saturated!(number); + let Some(hash) = host.block_hash(number_u64) else { interpreter.instruction_result = InstructionResult::FatalExternalError; return; }; diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 6938eead..4df6f62d 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -37,8 +37,10 @@ macro_rules! require_init_eof { #[macro_export] macro_rules! check { ($interp:expr, $min:ident) => { - // TODO: Force const-eval on the condition with a `const {}` block once they are stable - if !::enabled($crate::primitives::SpecId::$min) { + if const { + !::SPEC_ID + .is_enabled_in($crate::primitives::SpecId::$min) + } { $interp.instruction_result = $crate::InstructionResult::NotActivated; return; } diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 6481cdbf..a6ef59ed 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -113,6 +113,7 @@ impl Interpreter { bytecode, None, crate::primitives::Address::default(), + None, crate::primitives::Address::default(), U256::ZERO, ), @@ -470,13 +471,13 @@ mod tests { let mut interp = Interpreter::new(Contract::default(), u64::MAX, false); let mut host = crate::DummyHost::default(); - let table: InstructionTable = - crate::opcode::make_instruction_table::(); - let _ = interp.run(EMPTY_SHARED_MEMORY, &table, &mut host); + let table: &InstructionTable = + &crate::opcode::make_instruction_table::(); + let _ = interp.run(EMPTY_SHARED_MEMORY, table, &mut host); let host: &mut dyn Host = &mut host as &mut dyn Host; - let table: InstructionTable = - crate::opcode::make_instruction_table::(); - let _ = interp.run(EMPTY_SHARED_MEMORY, &table, host); + let table: &InstructionTable = + &crate::opcode::make_instruction_table::(); + let _ = interp.run(EMPTY_SHARED_MEMORY, table, host); } } diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index 49e511f6..304b7004 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -19,6 +19,9 @@ pub struct Contract { pub hash: Option, /// Target address of the account. Storage of this address is going to be modified. pub target_address: Address, + /// Address of the account the bytecode was loaded from. This can be different from target_address + /// in the case of DELEGATECALL or CALLCODE + pub bytecode_address: Option
, /// Caller of the EVM. pub caller: Address, /// Value send to contract from transaction or from CALL opcodes. @@ -33,6 +36,7 @@ impl Contract { bytecode: Bytecode, hash: Option, target_address: Address, + bytecode_address: Option
, caller: Address, call_value: U256, ) -> Self { @@ -43,6 +47,7 @@ impl Contract { bytecode, hash, target_address, + bytecode_address, caller, call_value, } @@ -55,11 +60,16 @@ impl Contract { TxKind::Call(caller) => caller, TxKind::Create => Address::ZERO, }; + let bytecode_address = match env.tx.transact_to { + TxKind::Call(caller) => Some(caller), + TxKind::Create => None, + }; Self::new( env.tx.data.clone(), bytecode, hash, contract_address, + bytecode_address, env.tx.caller, env.tx.value, ) @@ -78,6 +88,7 @@ impl Contract { bytecode, hash, call_context.target_address, + Some(call_context.bytecode_address), call_context.caller, call_context.call_value(), ) diff --git a/crates/interpreter/src/interpreter_action/call_inputs.rs b/crates/interpreter/src/interpreter_action/call_inputs.rs index 85d0c8fb..bc51ceac 100644 --- a/crates/interpreter/src/interpreter_action/call_inputs.rs +++ b/crates/interpreter/src/interpreter_action/call_inputs.rs @@ -130,6 +130,27 @@ pub enum CallScheme { DelegateCall, /// `STATICCALL` StaticCall, + /// `EXTCALL` + ExtCall, + /// `EXTSTATICCALL` + ExtStaticCall, + /// `EXTDELEGATECALL` + ExtDelegateCall, +} + +impl CallScheme { + /// Returns true if it is EOF EXT*CALL. + pub fn is_ext(&self) -> bool { + matches!( + self, + Self::ExtCall | Self::ExtStaticCall | Self::ExtDelegateCall + ) + } + + /// Returns true if it is ExtDelegateCall. + pub fn is_ext_delegate_call(&self) -> bool { + matches!(self, Self::ExtDelegateCall) + } } /// Call value. diff --git a/crates/interpreter/src/opcode/tables.rs b/crates/interpreter/src/opcode/tables.rs index 48a1b6cc..a2a66bc2 100644 --- a/crates/interpreter/src/opcode/tables.rs +++ b/crates/interpreter/src/opcode/tables.rs @@ -133,24 +133,15 @@ impl<'a, H: Host + ?Sized + 'a> InstructionTables<'a, H> { /// Make instruction table. #[inline] pub const fn make_instruction_table() -> InstructionTable { - // Force const-eval of the table creation, making this function trivial. - // TODO: Replace this with a `const {}` block once it is stable. - struct ConstTable { - _host: core::marker::PhantomData, - _spec: core::marker::PhantomData, - } - impl ConstTable { - const NEW: InstructionTable = { - let mut tables: InstructionTable = [control::unknown; 256]; - let mut i = 0; - while i < 256 { - tables[i] = instruction::(i as u8); - i += 1; - } - tables - }; + const { + let mut tables: InstructionTable = [control::unknown; 256]; + let mut i = 0; + while i < 256 { + tables[i] = instruction::(i as u8); + i += 1; + } + tables } - ConstTable::::NEW } /// Make boxed instruction table that calls `f` closure for every instruction. diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index f217827f..988f5a4e 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -6,7 +6,8 @@ keywords = ["no_std", "ethereum", "evm", "revm", "precompiles"] license = "MIT" name = "revm-precompile" repository = "https://github.com/bluealloy/revm" -version = "8.0.0" +version = "9.0.0" +readme = "../../README.md" [package.metadata.docs.rs] all-features = true @@ -21,13 +22,12 @@ rust_2018_idioms = "deny" all = "warn" [dependencies] -alloy-rlp = { version = "0.3.4", default-features = false, features = [ +alloy-rlp = { version = "0.3.7", default-features = false, features = [ "arrayvec", "derive", ] } -alloy-primitives = {version = "0.7.2"} -revm-primitives = { path = "../primitives", version = "5.0.0", default-features = false } +revm-primitives = { path = "../primitives", version = "6.0.0", default-features = false } once_cell = { version = "1.19", default-features = false, features = ["alloc"] } # ecRecover @@ -42,7 +42,7 @@ cometbft = { git = "https://github.com/bnb-chain/greenfield-cometbft-rs.git", re cometbft-light-client-verifier = { git = "https://github.com/bnb-chain/greenfield-cometbft-rs.git", rev = "1282547" } cometbft-proto = { git = "https://github.com/bnb-chain/greenfield-cometbft-rs.git", rev = "1282547" } cometbft-light-client = { git = "https://github.com/bnb-chain/greenfield-cometbft-rs.git", rev = "1282547" } -prost = { version = "0.12.3" } +prost = { version = "0.12.6" } bls_on_arkworks = "0.3.0" tendermint = { git = "https://github.com/bnb-chain/tendermint-rs-parlia", tag = "v0.1.0-beta.1", features = ["secp256k1"] } parity-bytes = { version = "0.1.2", default-features = false } @@ -68,6 +68,9 @@ p256 = { version = "0.13.2", optional = true, default-features = false, features "ecdsa", ] } +# utils +cfg-if = { version = "1.0", default-features = false } + [dev-dependencies] criterion = "0.5" rand = { version = "0.8", features = ["std"] } @@ -92,6 +95,7 @@ hashbrown = ["revm-primitives/hashbrown"] asm-keccak = ["revm-primitives/asm-keccak"] bsc = ["revm-primitives/bsc", "secp256k1", "secp256r1"] + optimism = ["revm-primitives/optimism", "secp256r1"] # Optimism default handler enabled Optimism handler register by default in EvmBuilder. optimism-default-handler = [ diff --git a/crates/precompile/src/double_sign.rs b/crates/precompile/src/double_sign.rs index fca24e86..9deefb1f 100644 --- a/crates/precompile/src/double_sign.rs +++ b/crates/precompile/src/double_sign.rs @@ -1,9 +1,8 @@ use crate::secp256k1; use crate::{Bytes, Error, Precompile, PrecompileResult, PrecompileWithAddress}; -use alloy_primitives::{BlockNumber, ChainId, U256}; use alloy_rlp::{Decodable, RlpDecodable, RlpEncodable}; use core::cmp::Ordering; -use revm_primitives::alloy_primitives::B512; +use revm_primitives::alloy_primitives::{BlockNumber, ChainId, B512, U256}; use revm_primitives::{keccak256, PrecompileOutput, B256}; /// Double sign evidence validation precompile for BSC. diff --git a/crates/precompile/src/fatal_precompile.rs b/crates/precompile/src/fatal_precompile.rs new file mode 100644 index 00000000..4dfaee8d --- /dev/null +++ b/crates/precompile/src/fatal_precompile.rs @@ -0,0 +1,35 @@ +use crate::primitives::{ + Address, Bytes, Env, Precompile, PrecompileErrors, PrecompileResult, StatefulPrecompile, +}; +use crate::PrecompileWithAddress; +use std::{string::String, sync::Arc}; + +/// Disable kzg precompile. This will return Fatal error on precompile call +pub fn fatal_precompile(address: Address, msg: String) -> PrecompileWithAddress { + PrecompileWithAddress(address, FatalPrecompile::new_precompile(msg)) +} + +/// Fatal precompile that returns Fatal error on precompile call +pub struct FatalPrecompile { + msg: String, +} + +impl FatalPrecompile { + /// Create a new fatal precompile + pub fn new(msg: String) -> Self { + Self { msg } + } + + /// Create a new stateful fatal precompile + pub fn new_precompile(msg: String) -> Precompile { + Precompile::Stateful(Arc::new(Self::new(msg))) + } +} + +impl StatefulPrecompile for FatalPrecompile { + fn call(&self, _: &Bytes, _: u64, _: &Env) -> PrecompileResult { + Err(PrecompileErrors::Fatal { + msg: self.msg.clone(), + }) + } +} diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 13b30e22..c340d0d1 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -15,6 +15,7 @@ pub mod bls12_381; pub mod bn128; mod cometbft; mod double_sign; +pub mod fatal_precompile; pub mod hash; mod iavl; pub mod identity; @@ -29,14 +30,18 @@ mod tendermint; mod tm_secp256k1; pub mod utilities; -use core::hash::Hash; -use once_cell::race::OnceBox; -#[doc(hidden)] -pub use revm_primitives as primitives; -pub use revm_primitives::{ +pub use fatal_precompile::fatal_precompile; + +pub use primitives::{ precompile::{PrecompileError as Error, *}, Address, Bytes, HashMap, HashSet, Log, B256, }; +#[doc(hidden)] +pub use revm_primitives as primitives; + +use cfg_if::cfg_if; +use core::hash::Hash; +use once_cell::race::OnceBox; use std::{boxed::Box, vec::Vec}; pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { @@ -269,24 +274,27 @@ impl Precompiles { static INSTANCE: OnceBox = OnceBox::new(); INSTANCE.get_or_init(|| { #[cfg(feature = "bsc")] - let precompiles = Self::feynman().clone(); + let mut precompiles = Self::feynman().clone(); #[cfg(not(feature = "bsc"))] - let precompiles = Self::berlin().clone(); + let mut precompiles = Self::berlin().clone(); - // Don't include KZG point evaluation precompile in no_std builds. - #[cfg(feature = "c-kzg")] - let precompiles = { - let mut precompiles = precompiles; - precompiles.extend([ - // EIP-4844: Shard Blob Transactions - kzg_point_evaluation::POINT_EVALUATION, - #[cfg(feature = "opbnb")] - bls::BLS_SIGNATURE_VALIDATION, - #[cfg(feature = "opbnb")] - cometbft::COMETBFT_LIGHT_BLOCK_VALIDATION, - ]); - precompiles - }; + // EIP-4844: Shard Blob Transactions + cfg_if! { + if #[cfg(feature = "c-kzg")] { + let precompile = kzg_point_evaluation::POINT_EVALUATION.clone(); + } else { + // TODO move constants to separate file. + let precompile = fatal_precompile(u64_to_address(0x0A), "c-kzg feature is not enabled".into()); + } + } + + precompiles.extend([ + precompile, + #[cfg(feature = "opbnb")] + bls::BLS_SIGNATURE_VALIDATION, + #[cfg(feature = "opbnb")] + cometbft::COMETBFT_LIGHT_BLOCK_VALIDATION, + ]); Box::new(precompiles) }) diff --git a/crates/primitives/CHANGELOG.md b/crates/primitives/CHANGELOG.md index 3aebb966..51acb106 100644 --- a/crates/primitives/CHANGELOG.md +++ b/crates/primitives/CHANGELOG.md @@ -6,6 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [6.0.0](https://github.com/bluealloy/revm/compare/revm-primitives-v5.0.0...revm-primitives-v6.0.0) - 2024-07-08 + +### Added +- *(Precompiles)* Throw fatal error if c-kzg is disabled ([#1589](https://github.com/bluealloy/revm/pull/1589)) +- *(Prague)* Add EIP-7702 ([#1565](https://github.com/bluealloy/revm/pull/1565)) +- add helper function to mape EVMError's Database error variant ([#1567](https://github.com/bluealloy/revm/pull/1567)) + +### Other +- *(README)* add rbuilder to used-by ([#1585](https://github.com/bluealloy/revm/pull/1585)) +- add utility function AccountInfo::from_bytecode ([#1577](https://github.com/bluealloy/revm/pull/1577)) +- replace AccessList with alloy version ([#1552](https://github.com/bluealloy/revm/pull/1552)) +- replace U256 with u64 in BLOCKHASH ([#1505](https://github.com/bluealloy/revm/pull/1505)) + ## [5.0.0](https://github.com/bluealloy/revm/compare/revm-primitives-v4.0.0...revm-primitives-v5.0.0) - 2024-06-20 ### Added diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 3b68b238..4587af8d 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["no_std", "ethereum", "evm", "revm", "types"] license = "MIT" name = "revm-primitives" repository = "https://github.com/bluealloy/revm" -version = "5.0.0" +version = "6.0.0" readme = "../../README.md" [package.metadata.docs.rs] @@ -22,6 +22,7 @@ rust_2018_idioms = "deny" all = "warn" [dependencies] +alloy-eips = { version = "0.1", default-features = false, features = ["k256"]} alloy-primitives = { version = "0.7.2", default-features = false, features = [ "rlp", ] } @@ -53,6 +54,7 @@ hex = { version = "0.4", default-features = false } default = ["std", "c-kzg", "portable"] std = [ "serde?/std", + "alloy-eips/std", "alloy-primitives/std", "hex/std", "bitvec/std", @@ -61,6 +63,7 @@ std = [ hashbrown = [] serde = [ "dep:serde", + "alloy-eips/serde", "alloy-primitives/serde", "hex/serde", "hashbrown/serde", @@ -68,7 +71,12 @@ serde = [ "bitflags/serde", "c-kzg?/serde", ] -arbitrary = ["std", "alloy-primitives/arbitrary", "bitflags/arbitrary"] +arbitrary = [ + "std", + "alloy-eips/arbitrary", + "alloy-primitives/arbitrary", + "bitflags/arbitrary" +] asm-keccak = ["alloy-primitives/asm-keccak"] portable = ["c-kzg?/portable"] diff --git a/crates/primitives/src/bytecode/eof.rs b/crates/primitives/src/bytecode/eof.rs index db6814b7..c4d9377f 100644 --- a/crates/primitives/src/bytecode/eof.rs +++ b/crates/primitives/src/bytecode/eof.rs @@ -215,8 +215,10 @@ mod test { assert_eq!(eof.data_slice(0, 4), &[0x01, 0x02, 0x03, 0x04]); assert_eq!(eof.data_slice(0, 5), &[0x01, 0x02, 0x03, 0x04]); assert_eq!(eof.data_slice(1, 2), &[0x02, 0x03]); - assert_eq!(eof.data_slice(10, 2), &[]); - assert_eq!(eof.data_slice(1, 0), &[]); - assert_eq!(eof.data_slice(10, 0), &[]); + + const EMPTY: &[u8] = &[]; + assert_eq!(eof.data_slice(10, 2), EMPTY); + assert_eq!(eof.data_slice(1, 0), EMPTY); + assert_eq!(eof.data_slice(10, 0), EMPTY); } } diff --git a/crates/primitives/src/bytecode/eof/header.rs b/crates/primitives/src/bytecode/eof/header.rs index c3482968..de1ad98a 100644 --- a/crates/primitives/src/bytecode/eof/header.rs +++ b/crates/primitives/src/bytecode/eof/header.rs @@ -240,7 +240,7 @@ mod tests { let (header, _) = EofHeader::decode(&input).unwrap(); assert_eq!(header.types_size, 4); assert_eq!(header.code_sizes, vec![1]); - assert_eq!(header.container_sizes, vec![]); + assert_eq!(header.container_sizes, Vec::::new()); assert_eq!(header.data_size, 0); } diff --git a/crates/primitives/src/db.rs b/crates/primitives/src/db.rs index 80c232cc..d0dfc464 100644 --- a/crates/primitives/src/db.rs +++ b/crates/primitives/src/db.rs @@ -22,7 +22,7 @@ pub trait Database { fn storage(&mut self, address: Address, index: U256) -> Result; /// Get block hash by block number. - fn block_hash(&mut self, number: U256) -> Result; + fn block_hash(&mut self, number: u64) -> Result; } /// EVM database commit interface. @@ -53,7 +53,7 @@ pub trait DatabaseRef { fn storage_ref(&self, address: Address, index: U256) -> Result; /// Get block hash by block number. - fn block_hash_ref(&self, number: U256) -> Result; + fn block_hash_ref(&self, number: u64) -> Result; } /// Wraps a [`DatabaseRef`] to provide a [`Database`] implementation. @@ -86,7 +86,7 @@ impl Database for WrapDatabaseRef { } #[inline] - fn block_hash(&mut self, number: U256) -> Result { + fn block_hash(&mut self, number: u64) -> Result { self.0.block_hash_ref(number) } } diff --git a/crates/primitives/src/db/components.rs b/crates/primitives/src/db/components.rs index c6348b92..5a2c5259 100644 --- a/crates/primitives/src/db/components.rs +++ b/crates/primitives/src/db/components.rs @@ -43,7 +43,7 @@ impl Database for DatabaseComponents { .map_err(Self::Error::State) } - fn block_hash(&mut self, number: U256) -> Result { + fn block_hash(&mut self, number: u64) -> Result { self.block_hash .block_hash(number) .map_err(Self::Error::BlockHash) @@ -69,7 +69,7 @@ impl DatabaseRef for DatabaseComponents { .map_err(Self::Error::State) } - fn block_hash_ref(&self, number: U256) -> Result { + fn block_hash_ref(&self, number: u64) -> Result { self.block_hash .block_hash(number) .map_err(Self::Error::BlockHash) diff --git a/crates/primitives/src/db/components/block_hash.rs b/crates/primitives/src/db/components/block_hash.rs index a0a0fe21..8093f278 100644 --- a/crates/primitives/src/db/components/block_hash.rs +++ b/crates/primitives/src/db/components/block_hash.rs @@ -1,7 +1,7 @@ //! BlockHash database component from [`crate::db::Database`] //! it is used inside [`crate::db::DatabaseComponents`] -use crate::{B256, U256}; +use crate::B256; use auto_impl::auto_impl; use core::ops::Deref; use std::sync::Arc; @@ -11,7 +11,7 @@ pub trait BlockHash { type Error; /// Get block hash by block number - fn block_hash(&mut self, number: U256) -> Result; + fn block_hash(&mut self, number: u64) -> Result; } #[auto_impl(&, &mut, Box, Rc, Arc)] @@ -19,7 +19,7 @@ pub trait BlockHashRef { type Error; /// Get block hash by block number - fn block_hash(&self, number: U256) -> Result; + fn block_hash(&self, number: u64) -> Result; } impl BlockHash for &T @@ -28,7 +28,7 @@ where { type Error = ::Error; - fn block_hash(&mut self, number: U256) -> Result { + fn block_hash(&mut self, number: u64) -> Result { BlockHashRef::block_hash(*self, number) } } @@ -39,7 +39,7 @@ where { type Error = ::Error; - fn block_hash(&mut self, number: U256) -> Result { + fn block_hash(&mut self, number: u64) -> Result { self.deref().block_hash(number) } } diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index d71571a4..d3a8dc1e 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -1,13 +1,15 @@ +pub mod eip7702; pub mod handler_cfg; -use alloy_primitives::TxKind; +pub use eip7702::AuthorizationList; pub use handler_cfg::{CfgEnvWithHandlerCfg, EnvWithHandlerCfg, HandlerCfg}; use crate::{ - calc_blob_gasprice, Account, Address, Bytes, InvalidHeader, InvalidTransaction, Spec, SpecId, - B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, U256, - VERSIONED_HASH_VERSION_KZG, + calc_blob_gasprice, AccessListItem, Account, Address, Bytes, InvalidHeader, InvalidTransaction, + Spec, SpecId, B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, + U256, VERSIONED_HASH_VERSION_KZG, }; +use alloy_primitives::TxKind; use core::cmp::{min, Ordering}; use core::hash::Hash; use std::boxed::Box; @@ -92,6 +94,25 @@ impl Env { /// Return initial spend gas (Gas needed to execute transaction). #[inline] pub fn validate_tx(&self) -> Result<(), InvalidTransaction> { + // Check if the transaction's chain id is correct + if let Some(tx_chain_id) = self.tx.chain_id { + if tx_chain_id != self.cfg.chain_id { + return Err(InvalidTransaction::InvalidChainId); + } + } + + // Check if gas_limit is more than block_gas_limit + if !self.cfg.is_block_gas_limit_disabled() + && U256::from(self.tx.gas_limit) > self.block.gas_limit + { + return Err(InvalidTransaction::CallerGasLimitMoreThanBlock); + } + + // Check that access list is empty for transactions before BERLIN + if !SPEC::enabled(SpecId::BERLIN) && !self.tx.access_list.is_empty() { + return Err(InvalidTransaction::AccessListNotSupported); + } + // BASEFEE tx check if SPEC::enabled(SpecId::LONDON) { if let Some(priority_fee) = self.tx.gas_priority_fee { @@ -109,13 +130,6 @@ impl Env { } } - // Check if gas_limit is more than block_gas_limit - if !self.cfg.is_block_gas_limit_disabled() - && U256::from(self.tx.gas_limit) > self.block.gas_limit - { - return Err(InvalidTransaction::CallerGasLimitMoreThanBlock); - } - // EIP-3860: Limit and meter initcode if SPEC::enabled(SpecId::SHANGHAI) && self.tx.transact_to.is_create() { let max_initcode_size = self @@ -128,65 +142,66 @@ impl Env { } } - // Check if the transaction's chain id is correct - if let Some(tx_chain_id) = self.tx.chain_id { - if tx_chain_id != self.cfg.chain_id { - return Err(InvalidTransaction::InvalidChainId); - } - } - - // Check that access list is empty for transactions before BERLIN - if !SPEC::enabled(SpecId::BERLIN) && !self.tx.access_list.is_empty() { - return Err(InvalidTransaction::AccessListNotSupported); + // - For before CANCUN, check that `blob_hashes` and `max_fee_per_blob_gas` are empty / not set + if !SPEC::enabled(SpecId::CANCUN) + && (self.tx.max_fee_per_blob_gas.is_some() || !self.tx.blob_hashes.is_empty()) + { + return Err(InvalidTransaction::BlobVersionedHashesNotSupported); } - // - For CANCUN and later, check that the gas price is not more than the tx max - // - For before CANCUN, check that `blob_hashes` and `max_fee_per_blob_gas` are empty / not set - if SPEC::enabled(SpecId::CANCUN) { - // Presence of max_fee_per_blob_gas means that this is blob transaction. - if let Some(max) = self.tx.max_fee_per_blob_gas { - // ensure that the user was willing to at least pay the current blob gasprice - let price = self.block.get_blob_gasprice().expect("already checked"); - if U256::from(price) > max { - return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); - } + // Presence of max_fee_per_blob_gas means that this is blob transaction. + if let Some(max) = self.tx.max_fee_per_blob_gas { + // ensure that the user was willing to at least pay the current blob gasprice + let price = self.block.get_blob_gasprice().expect("already checked"); + if U256::from(price) > max { + return Err(InvalidTransaction::BlobGasPriceGreaterThanMax); + } - // there must be at least one blob - if self.tx.blob_hashes.is_empty() { - return Err(InvalidTransaction::EmptyBlobs); - } + // there must be at least one blob + if self.tx.blob_hashes.is_empty() { + return Err(InvalidTransaction::EmptyBlobs); + } - // The field `to` deviates slightly from the semantics with the exception - // that it MUST NOT be nil and therefore must always represent - // a 20-byte address. This means that blob transactions cannot - // have the form of a create transaction. - if self.tx.transact_to.is_create() { - return Err(InvalidTransaction::BlobCreateTransaction); - } + // The field `to` deviates slightly from the semantics with the exception + // that it MUST NOT be nil and therefore must always represent + // a 20-byte address. This means that blob transactions cannot + // have the form of a create transaction. + if self.tx.transact_to.is_create() { + return Err(InvalidTransaction::BlobCreateTransaction); + } - // all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG - for blob in self.tx.blob_hashes.iter() { - if blob[0] != VERSIONED_HASH_VERSION_KZG { - return Err(InvalidTransaction::BlobVersionNotSupported); - } + // all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG + for blob in self.tx.blob_hashes.iter() { + if blob[0] != VERSIONED_HASH_VERSION_KZG { + return Err(InvalidTransaction::BlobVersionNotSupported); } + } - // ensure the total blob gas spent is at most equal to the limit - // assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK - let num_blobs = self.tx.blob_hashes.len(); - if num_blobs > MAX_BLOB_NUMBER_PER_BLOCK as usize { - return Err(InvalidTransaction::TooManyBlobs { - have: num_blobs, - max: MAX_BLOB_NUMBER_PER_BLOCK as usize, - }); - } + // ensure the total blob gas spent is at most equal to the limit + // assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK + let num_blobs = self.tx.blob_hashes.len(); + if num_blobs > MAX_BLOB_NUMBER_PER_BLOCK as usize { + return Err(InvalidTransaction::TooManyBlobs { + have: num_blobs, + max: MAX_BLOB_NUMBER_PER_BLOCK as usize, + }); } } else { + // if max_fee_per_blob_gas is not set, then blob_hashes must be empty if !self.tx.blob_hashes.is_empty() { return Err(InvalidTransaction::BlobVersionedHashesNotSupported); } - if self.tx.max_fee_per_blob_gas.is_some() { - return Err(InvalidTransaction::MaxFeePerBlobGasNotSupported); + } + + // check if EIP-7702 transaction is enabled. + if !SPEC::enabled(SpecId::PRAGUE) && self.tx.authorization_list.is_some() { + return Err(InvalidTransaction::AuthorizationListNotSupported); + } + + if self.tx.authorization_list.is_some() { + // Check if other fields are unset. + if self.tx.max_fee_per_blob_gas.is_some() || !self.tx.blob_hashes.is_empty() { + return Err(InvalidTransaction::AuthorizationListInvalidFields); } } @@ -509,6 +524,7 @@ pub struct TxEnv { pub value: U256, /// The data of the transaction. pub data: Bytes, + /// The nonce of the transaction. /// /// Caution: If set to `None`, then nonce validation against the account's nonce is skipped: [InvalidTransaction::NonceTooHigh] and [InvalidTransaction::NonceTooLow] @@ -526,7 +542,7 @@ pub struct TxEnv { /// Added in [EIP-2930]. /// /// [EIP-2930]: https://eips.ethereum.org/EIPS/eip-2930 - pub access_list: Vec<(Address, Vec)>, + pub access_list: Vec, /// The priority fee per gas. /// @@ -550,6 +566,14 @@ pub struct TxEnv { /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 pub max_fee_per_blob_gas: Option, + /// List of authorizations, that contains the signature that authorizes this + /// caller to place the code to signer account. + /// + /// Set EOA account code for one transaction + /// + /// [EIP-Set EOA account code for one transaction](https://eips.ethereum.org/EIPS/eip-7702) + pub authorization_list: Option, + #[cfg_attr(feature = "serde", serde(flatten))] #[cfg(feature = "optimism")] /// Optimism fields. @@ -598,6 +622,7 @@ impl Default for TxEnv { access_list: Vec::new(), blob_hashes: Vec::new(), max_fee_per_blob_gas: None, + authorization_list: None, #[cfg(feature = "optimism")] optimism: OptimismFields::default(), #[cfg(feature = "bsc")] @@ -719,7 +744,10 @@ mod tests { #[test] fn test_validate_tx_access_list() { let mut env = Env::default(); - env.tx.access_list = vec![(Address::ZERO, vec![])]; + env.tx.access_list = vec![AccessListItem { + address: Address::ZERO, + storage_keys: vec![], + }]; assert_eq!( env.validate_tx::(), Err(InvalidTransaction::AccessListNotSupported) diff --git a/crates/primitives/src/env/eip7702.rs b/crates/primitives/src/env/eip7702.rs new file mode 100644 index 00000000..96a685d5 --- /dev/null +++ b/crates/primitives/src/env/eip7702.rs @@ -0,0 +1,36 @@ +use alloy_eips::eip7702::{RecoveredAuthorization, SignedAuthorization}; +use alloy_primitives::Signature; +use std::{boxed::Box, vec::Vec}; + +/// Authorization list for EIP-7702 transaction type. +#[derive(Clone, Debug, Eq, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum AuthorizationList { + Signed(Vec>), + Recovered(Vec), +} + +impl AuthorizationList { + /// Returns length of the authorization list. + pub fn len(&self) -> usize { + match self { + Self::Signed(signed) => signed.len(), + Self::Recovered(recovered) => recovered.len(), + } + } + + /// Returns true if the authorization list is empty. + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns iterator of recovered Authorizations. + pub fn recovered_iter<'a>(&'a self) -> Box + 'a> { + match self { + Self::Signed(signed) => { + Box::new(signed.iter().map(|signed| signed.clone().into_recovered())) + } + Self::Recovered(recovered) => Box::new(recovered.clone().into_iter()), + } + } +} diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 35019aa0..78e939d5 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -19,6 +19,7 @@ pub mod result; pub mod specification; pub mod state; pub mod utilities; +pub use alloy_eips::eip2930::{AccessList, AccessListItem}; pub use alloy_primitives::{ self, address, b256, bytes, fixed_bytes, hex, hex_literal, ruint, uint, Address, Bytes, FixedBytes, Log, LogData, TxKind, B256, I256, U256, diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 2a61883a..f6c883da 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -152,6 +152,22 @@ pub enum EVMError { Precompile(String), } +impl EVMError { + /// Maps a `DBError` to a new error type using the provided closure, leaving other variants unchanged. + pub fn map_db_err(self, op: F) -> EVMError + where + F: FnOnce(DBError) -> E, + { + match self { + Self::Transaction(e) => EVMError::Transaction(e), + Self::Header(e) => EVMError::Header(e), + Self::Database(e) => EVMError::Database(op(e)), + Self::Precompile(e) => EVMError::Precompile(e), + Self::Custom(e) => EVMError::Custom(e), + } + } +} + #[cfg(feature = "std")] impl std::error::Error for EVMError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { @@ -252,6 +268,10 @@ pub enum InvalidTransaction { BlobVersionNotSupported, /// EOF crate should have `to` address EofCrateShouldHaveToAddress, + /// EIP-7702 is not enabled. + AuthorizationListNotSupported, + /// EIP-7702 transaction has invalid fields set. + AuthorizationListInvalidFields, /// System transactions are not supported post-regolith hardfork. /// /// Before the Regolith hardfork, there was a special field in the `Deposit` transaction @@ -343,6 +363,10 @@ impl fmt::Display for InvalidTransaction { } Self::BlobVersionNotSupported => write!(f, "blob version not supported"), Self::EofCrateShouldHaveToAddress => write!(f, "EOF crate should have `to` address"), + Self::AuthorizationListNotSupported => write!(f, "authorization list not supported"), + Self::AuthorizationListInvalidFields => { + write!(f, "authorization list tx has invalid fields") + } #[cfg(feature = "optimism")] Self::DepositSystemTxPostRegolith => { write!( @@ -400,7 +424,7 @@ pub enum SuccessReason { pub enum HaltReason { OutOfGas(OutOfGasError), OpcodeNotFound, - InvalidEFOpcode, + InvalidFEOpcode, InvalidJump, NotActivated, StackUnderflow, diff --git a/crates/primitives/src/state.rs b/crates/primitives/src/state.rs index d1f6c9df..fc4d1e60 100644 --- a/crates/primitives/src/state.rs +++ b/crates/primitives/src/state.rs @@ -310,6 +310,17 @@ impl AccountInfo { ..Default::default() } } + + pub fn from_bytecode(bytecode: Bytecode) -> Self { + let hash = bytecode.hash_slow(); + + AccountInfo { + balance: U256::ZERO, + nonce: 1, + code: Some(bytecode), + code_hash: hash, + } + } } #[cfg(test)] diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 0822ca73..c45aa73b 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -6,6 +6,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.0.0](https://github.com/bluealloy/revm/compare/revm-v10.0.0...revm-v11.0.0) - 2024-07-08 + +### Added +- add bytecode_address from CallInputs to Contract during construction. ([#1568](https://github.com/bluealloy/revm/pull/1568)) +- *(Prague)* Add EIP-7702 ([#1565](https://github.com/bluealloy/revm/pull/1565)) +- *(EOF)* disallow ExtDelegateCall to legacy bytecode ([#1572](https://github.com/bluealloy/revm/pull/1572)) +- *(EOF)* Add target address expansion checks ([#1570](https://github.com/bluealloy/revm/pull/1570)) + +### Other +- bump precompile to v9.0.0 ([#1590](https://github.com/bluealloy/revm/pull/1590)) +- *(README)* add rbuilder to used-by ([#1585](https://github.com/bluealloy/revm/pull/1585)) +- Use HandleOrRuntime to allow alloydb/ethersdb to hold a custom runtime ([#1576](https://github.com/bluealloy/revm/pull/1576)) +- store tokio::runtime::Handle in ethers/alloyDB ([#1557](https://github.com/bluealloy/revm/pull/1557)) +- use const blocks ([#1522](https://github.com/bluealloy/revm/pull/1522)) +- fix compile for alloydb ([#1559](https://github.com/bluealloy/revm/pull/1559)) +- replace AccessList with alloy version ([#1552](https://github.com/bluealloy/revm/pull/1552)) +- replace U256 with u64 in BLOCKHASH ([#1505](https://github.com/bluealloy/revm/pull/1505)) + ## [10.0.0](https://github.com/bluealloy/revm/compare/revm-v9.0.0...revm-v10.0.0) - 2024-06-20 ### Added diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 26362540..cd90af16 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["no_std", "ethereum", "evm", "revm"] license = "MIT" name = "revm" repository = "https://github.com/bluealloy/revm" -version = "10.0.0" +version = "11.0.0" readme = "../../README.md" [package.metadata.docs.rs] @@ -23,8 +23,8 @@ all = "warn" [dependencies] # revm -revm-interpreter = { path = "../interpreter", version = "6.0.0", default-features = false } -revm-precompile = { path = "../precompile", version = "8.0.0", default-features = false } +revm-interpreter = { path = "../interpreter", version = "7.0.0", default-features = false } +revm-precompile = { path = "../precompile", version = "9.0.0", default-features = false } # misc auto_impl = { version = "1.2", default-features = false } diff --git a/crates/revm/src/bsc/handler_register.rs b/crates/revm/src/bsc/handler_register.rs index d55c567c..6975a970 100644 --- a/crates/revm/src/bsc/handler_register.rs +++ b/crates/revm/src/bsc/handler_register.rs @@ -1,5 +1,6 @@ //! Handler related to BNB-Smart-chain +use crate::primitives::KECCAK_EMPTY; use crate::{ handler::register::EvmHandler, interpreter::Gas, @@ -9,7 +10,7 @@ use crate::{ }, Context, FrameResult, }; -use revm_interpreter::{gas, InternalResult, SuccessOrHalt}; +use revm_interpreter::{gas, SuccessOrHalt}; use std::sync::Arc; pub const SYSTEM_ADDRESS: Address = address!("fffffffffffffffffffffffffffffffffffffffe"); @@ -35,9 +36,20 @@ pub fn validate_initial_tx_gas( let input = &env.tx.data; let is_create = env.tx.transact_to.is_create(); let access_list = &env.tx.access_list; - - let initial_gas_spend = - gas::validate_initial_tx_gas(SPEC::SPEC_ID, input, is_create, access_list); + let authorization_list_num = env + .tx + .authorization_list + .as_ref() + .map(|l| l.len() as u64) + .unwrap_or_default(); + + let initial_gas_spend = gas::validate_initial_tx_gas( + SPEC::SPEC_ID, + input, + is_create, + access_list, + authorization_list_num, + ); // Additional check to see if limit is big enough to cover initial gas. if initial_gas_spend > env.tx.gas_limit { @@ -84,7 +96,7 @@ pub fn output( context: &mut Context, result: FrameResult, ) -> Result> { - core::mem::replace(&mut context.evm.error, Ok(()))?; + context.evm.take_error()?; // used gas with refund calculated. let gas_refunded = if context .evm @@ -103,7 +115,17 @@ pub fn output( let instruction_result = result.into_interpreter_result(); // reset journal and return present state. - let (state, logs) = context.evm.journaled_state.finalize(); + let (mut state, logs) = context.evm.journaled_state.finalize(); + + // clear code of authorized accounts. + for authorized in core::mem::take(&mut context.evm.inner.valid_authorizations).into_iter() { + let account = state + .get_mut(&authorized) + .expect("Authorized account must exist"); + account.info.code = None; + account.info.code_hash = KECCAK_EMPTY; + account.storage.clear(); + } let result = match instruction_result.result.into() { SuccessOrHalt::Success(reason) => ExecutionResult::Success { @@ -121,11 +143,8 @@ pub fn output( reason, gas_used: final_gas_used, }, - // Only three internal return flags. - flag @ (SuccessOrHalt::FatalExternalError - | SuccessOrHalt::Internal(InternalResult::InternalContinue) - | SuccessOrHalt::Internal(InternalResult::InternalCallOrCreate) - | SuccessOrHalt::Internal(InternalResult::CreateInitCodeStartingEF00)) => { + // Only two internal return flags. + flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => { panic!( "Encountered unexpected internal return flag: {:?} with instruction result: {:?}", flag, instruction_result diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index cc1fd20d..d715296b 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -108,9 +108,9 @@ impl Host for Context { &mut self.evm.env } - fn block_hash(&mut self, number: U256) -> Option { + fn block_hash(&mut self, number: u64) -> Option { let block_number = as_usize_saturated!(self.env().block.number); - let requested_number = as_usize_saturated!(number); + let requested_number = usize::try_from(number).unwrap_or(usize::MAX); let Some(diff) = block_number.checked_sub(requested_number) else { return Some(B256::ZERO); diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index d8270c7e..83299624 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -7,7 +7,7 @@ use crate::{ interpreter::{ return_ok, CallInputs, Contract, Gas, InstructionResult, Interpreter, InterpreterResult, }, - primitives::{Address, Bytes, EVMError, Env, U256}, + primitives::{Address, Bytes, EVMError, Env, EOF_MAGIC_BYTES, U256}, ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, }; use core::{ @@ -180,9 +180,17 @@ impl EvmContext { .inner .journaled_state .load_code(inputs.bytecode_address, &mut self.inner.db)?; + let code_hash = account.info.code_hash(); let bytecode = account.info.code.clone().unwrap_or_default(); + // ExtDelegateCall is not allowed to call non-EOF contracts. + if inputs.scheme.is_ext_delegate_call() + && bytecode.bytes_slice().get(..2) != Some(&EOF_MAGIC_BYTES) + { + return return_result(InstructionResult::InvalidExtDelegateCallTarget); + } + // Create subroutine checkpoint let checkpoint = self.journaled_state.checkpoint(); @@ -294,6 +302,7 @@ pub(crate) mod test_utils { journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), db, error: Ok(()), + valid_authorizations: Vec::new(), #[cfg(feature = "optimism")] l1_block_info: None, }, @@ -309,6 +318,7 @@ pub(crate) mod test_utils { journaled_state: JournaledState::new(SpecId::CANCUN, HashSet::new()), db, error: Ok(()), + valid_authorizations: Default::default(), #[cfg(feature = "optimism")] l1_block_info: None, }, diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index c1662951..36ddad1b 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -8,14 +8,14 @@ use crate::{ }, journaled_state::JournaledState, primitives::{ - keccak256, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, EVMError, Env, - Eof, HashSet, Spec, + keccak256, AccessListItem, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, + EVMError, Env, Eof, HashSet, Spec, SpecId::{self, *}, B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, }, FrameOrResult, JournalCheckpoint, CALL_STACK_LIMIT, }; -use std::{boxed::Box, sync::Arc}; +use std::{boxed::Box, sync::Arc, vec::Vec}; /// EVM contexts contains data that EVM needs for execution. #[derive(Debug)] @@ -29,6 +29,8 @@ pub struct InnerEvmContext { pub db: DB, /// Error that happened during execution. pub error: Result<(), EVMError>, + /// EIP-7702 Authorization list of accounts that needs to be cleared. + pub valid_authorizations: Vec
, /// Used as temporary value holder to store L1 block info. #[cfg(feature = "optimism")] pub l1_block_info: Option, @@ -44,6 +46,7 @@ where journaled_state: self.journaled_state.clone(), db: self.db.clone(), error: self.error.clone(), + valid_authorizations: self.valid_authorizations.clone(), #[cfg(feature = "optimism")] l1_block_info: self.l1_block_info.clone(), } @@ -57,6 +60,7 @@ impl InnerEvmContext { journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), db, error: Ok(()), + valid_authorizations: Default::default(), #[cfg(feature = "optimism")] l1_block_info: None, } @@ -70,6 +74,7 @@ impl InnerEvmContext { journaled_state: JournaledState::new(SpecId::LATEST, HashSet::new()), db, error: Ok(()), + valid_authorizations: Default::default(), #[cfg(feature = "optimism")] l1_block_info: None, } @@ -85,6 +90,7 @@ impl InnerEvmContext { journaled_state: self.journaled_state, db, error: Ok(()), + valid_authorizations: Default::default(), #[cfg(feature = "optimism")] l1_block_info: self.l1_block_info, } @@ -101,9 +107,16 @@ impl InnerEvmContext { /// Loading of accounts/storages is needed to make them warm. #[inline] pub fn load_access_list(&mut self) -> Result<(), EVMError> { - for (address, slots) in self.env.tx.access_list.iter() { - self.journaled_state - .initial_account_load(*address, slots, &mut self.db)?; + for AccessListItem { + address, + storage_keys, + } in self.env.tx.access_list.iter() + { + self.journaled_state.initial_account_load( + *address, + storage_keys.iter().map(|i| U256::from_be_bytes(i.0)), + &mut self.db, + )?; } Ok(()) } @@ -122,7 +135,7 @@ impl InnerEvmContext { /// Fetch block hash from database. #[inline] - pub fn block_hash(&mut self, number: U256) -> Result> { + pub fn block_hash(&mut self, number: u64) -> Result> { self.db.block_hash(number).map_err(EVMError::Database) } @@ -332,6 +345,7 @@ impl InnerEvmContext { Bytecode::Eof(Arc::new(initcode.clone())), None, created_address, + None, inputs.caller, inputs.value, ); @@ -416,7 +430,8 @@ impl InnerEvmContext { } // Prague EOF - if spec_id.is_enabled_in(PRAGUE_EOF) && inputs.init_code.get(..2) == Some(&[0xEF, 00]) { + if spec_id.is_enabled_in(PRAGUE_EOF) && inputs.init_code.get(..2) == Some(&EOF_MAGIC_BYTES) + { return return_error(InstructionResult::CreateInitCodeStartingEF00); } @@ -470,6 +485,7 @@ impl InnerEvmContext { bytecode, Some(init_code_hash), created_address, + None, inputs.caller, inputs.value, ); diff --git a/crates/revm/src/db.rs b/crates/revm/src/db.rs index f7c4904a..febad10c 100644 --- a/crates/revm/src/db.rs +++ b/crates/revm/src/db.rs @@ -1,5 +1,8 @@ //! [Database] implementations. +#[cfg(any(feature = "alloydb", feature = "ethersdb"))] +mod utils; + #[cfg(feature = "alloydb")] mod alloydb; pub mod emptydb; diff --git a/crates/revm/src/db/alloydb.rs b/crates/revm/src/db/alloydb.rs index 40945c68..1caf4151 100644 --- a/crates/revm/src/db/alloydb.rs +++ b/crates/revm/src/db/alloydb.rs @@ -1,66 +1,85 @@ use crate::{ db::{Database, DatabaseRef}, - primitives::{AccountInfo, Address, Bytecode, B256, KECCAK_EMPTY, U256}, + primitives::{AccountInfo, Address, Bytecode, B256, U256}, }; use alloy_eips::BlockId; use alloy_provider::{Network, Provider}; use alloy_transport::{Transport, TransportError}; use std::future::IntoFuture; -use tokio::runtime::{Builder, Handle}; +use tokio::runtime::{Handle, Runtime}; + +use super::utils::HandleOrRuntime; /// An alloy-powered REVM [Database]. /// /// When accessing the database, it'll use the given provider to fetch the corresponding account's data. -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct AlloyDB> { /// The provider to fetch the data from. provider: P, /// The block number on which the queries will be based on. block_number: BlockId, + /// handle to the tokio runtime + rt: HandleOrRuntime, _marker: std::marker::PhantomData (T, N)>, } impl> AlloyDB { - /// Create a new AlloyDB instance, with a [Provider] and a block (Use None for latest). - pub fn new(provider: P, block_number: BlockId) -> Self { + /// Create a new AlloyDB instance, with a [Provider] and a block. + /// + /// Returns `None` if no tokio runtime is available or if the current runtime is a current-thread runtime. + pub fn new(provider: P, block_number: BlockId) -> Option { + let rt = match Handle::try_current() { + Ok(handle) => match handle.runtime_flavor() { + tokio::runtime::RuntimeFlavor::CurrentThread => return None, + _ => HandleOrRuntime::Handle(handle), + }, + Err(_) => return None, + }; + Some(Self { + provider, + block_number, + rt, + _marker: std::marker::PhantomData, + }) + } + + /// Create a new AlloyDB instance, with a provider and a block and a runtime. + /// + /// Refer to [tokio::runtime::Builder] on how to create a runtime if you are in synchronous world. + /// If you are already using something like [tokio::main], call AlloyDB::new instead. + pub fn with_runtime(provider: P, block_number: BlockId, runtime: Runtime) -> Self { + let rt = HandleOrRuntime::Runtime(runtime); Self { provider, block_number, + rt, + _marker: std::marker::PhantomData, + } + } + + /// Create a new AlloyDB instance, with a provider and a block and a runtime handle. + /// + /// This generally allows you to pass any valid runtime handle, refer to [tokio::runtime::Handle] on how + /// to obtain a handle. If you are already in asynchronous world, like [tokio::main], use AlloyDB::new instead. + pub fn with_handle(provider: P, block_number: BlockId, handle: Handle) -> Self { + let rt = HandleOrRuntime::Handle(handle); + Self { + provider, + block_number, + rt, _marker: std::marker::PhantomData, } } /// Internal utility function that allows us to block on a future regardless of the runtime flavor. #[inline] - fn block_on(f: F) -> F::Output + fn block_on(&self, f: F) -> F::Output where F: std::future::Future + Send, F::Output: Send, { - match Handle::try_current() { - Ok(handle) => match handle.runtime_flavor() { - // This is essentially equal to tokio::task::spawn_blocking because tokio doesn't - // allow the current_thread runtime to block_in_place. - // See for more info. - tokio::runtime::RuntimeFlavor::CurrentThread => std::thread::scope(move |s| { - s.spawn(move || { - Builder::new_current_thread() - .enable_all() - .build() - .unwrap() - .block_on(f) - }) - .join() - .unwrap() - }), - _ => tokio::task::block_in_place(move || handle.block_on(f)), - }, - Err(_) => Builder::new_current_thread() - .enable_all() - .build() - .unwrap() - .block_on(f), - } + self.rt.block_on(f) } /// Set the block number on which the queries will be based on. @@ -93,7 +112,7 @@ impl> DatabaseRef for AlloyD ) }; - let (nonce, balance, code) = Self::block_on(f); + let (nonce, balance, code) = self.block_on(f); let balance = balance?; let code = Bytecode::new_raw(code?.0.into()); @@ -103,16 +122,11 @@ impl> DatabaseRef for AlloyD Ok(Some(AccountInfo::new(balance, nonce, code_hash, code))) } - fn block_hash_ref(&self, number: U256) -> Result { - // Saturate usize - if number > U256::from(u64::MAX) { - return Ok(KECCAK_EMPTY); - } - - let block = Self::block_on( + fn block_hash_ref(&self, number: u64) -> Result { + let block = self.block_on( self.provider // SAFETY: We know number <= u64::MAX, so we can safely convert it to u64 - .get_block_by_number(number.to::().into(), false), + .get_block_by_number(number.into(), false), )?; // SAFETY: If the number is given, the block is supposed to be finalized, so unwrapping is safe. Ok(B256::new(*block.unwrap().header.hash.unwrap())) @@ -128,7 +142,7 @@ impl> DatabaseRef for AlloyD .provider .get_storage_at(address, index) .block_id(self.block_number); - let slot_val = Self::block_on(f.into_future())?; + let slot_val = self.block_on(f.into_future())?; Ok(slot_val) } } @@ -152,7 +166,7 @@ impl> Database for AlloyDB Result { + fn block_hash(&mut self, number: u64) -> Result { ::block_hash_ref(self, number) } } @@ -177,7 +191,7 @@ mod tests { .parse() .unwrap(); - let acc_info = alloydb.basic_ref(address).unwrap().unwrap(); + let acc_info = alloydb.unwrap().basic_ref(address).unwrap().unwrap(); assert!(acc_info.exists()); } } diff --git a/crates/revm/src/db/emptydb.rs b/crates/revm/src/db/emptydb.rs index 23598e8c..3d14ab23 100644 --- a/crates/revm/src/db/emptydb.rs +++ b/crates/revm/src/db/emptydb.rs @@ -72,7 +72,7 @@ impl Database for EmptyDBTyped { } #[inline] - fn block_hash(&mut self, number: U256) -> Result { + fn block_hash(&mut self, number: u64) -> Result { ::block_hash_ref(self, number) } } @@ -96,7 +96,7 @@ impl DatabaseRef for EmptyDBTyped { } #[inline] - fn block_hash_ref(&self, number: U256) -> Result { + fn block_hash_ref(&self, number: u64) -> Result { Ok(keccak256(number.to_string().as_bytes())) } } @@ -110,21 +110,21 @@ mod tests { fn conform_block_hash_calculation() { let db = EmptyDB::new(); assert_eq!( - db.block_hash_ref(U256::from(0)), + db.block_hash_ref(0u64), Ok(b256!( "044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d" )) ); assert_eq!( - db.block_hash_ref(U256::from(1)), + db.block_hash_ref(1u64), Ok(b256!( "c89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6" )) ); assert_eq!( - db.block_hash_ref(U256::from(100)), + db.block_hash_ref(100u64), Ok(b256!( "8c18210df0d9514f2d2e5d8ca7c100978219ee80d3968ad850ab5ead208287b3" )) diff --git a/crates/revm/src/db/ethersdb.rs b/crates/revm/src/db/ethersdb.rs index cc318577..6e4f813a 100644 --- a/crates/revm/src/db/ethersdb.rs +++ b/crates/revm/src/db/ethersdb.rs @@ -2,64 +2,104 @@ use std::sync::Arc; use ethers_core::types::{Block, BlockId, TxHash, H160 as eH160, H256, U64 as eU64}; use ethers_providers::Middleware; -use tokio::runtime::{Builder, Handle, RuntimeFlavor}; +use tokio::runtime::{Handle, Runtime}; -use crate::primitives::{AccountInfo, Address, Bytecode, B256, KECCAK_EMPTY, U256}; +use crate::primitives::{AccountInfo, Address, Bytecode, B256, U256}; use crate::{Database, DatabaseRef}; -#[derive(Debug, Clone)] +use super::utils::HandleOrRuntime; + +#[derive(Debug)] pub struct EthersDB { client: Arc, block_number: Option, + rt: HandleOrRuntime, } impl EthersDB { - /// create ethers db connector inputs are url and block on what we are basing our database (None for latest) + /// Create ethers db connector inputs are url and block on what we are basing our database (None for latest). + /// + /// Returns `None` if no tokio runtime is available or if the current runtime is a current-thread runtime. pub fn new(client: Arc, block_number: Option) -> Option { - let block_number: Option = if block_number.is_some() { - block_number + let rt = match Handle::try_current() { + Ok(handle) => match handle.runtime_flavor() { + tokio::runtime::RuntimeFlavor::CurrentThread => return None, + _ => HandleOrRuntime::Handle(handle), + }, + Err(_) => return None, + }; + + if block_number.is_some() { + Some(Self { + client, + block_number, + rt, + }) } else { - Some(BlockId::from( - Self::block_on(client.get_block_number()).ok()?, - )) + let mut instance = Self { + client, + block_number: None, + rt, + }; + instance.block_number = Some(BlockId::from( + instance.block_on(instance.client.get_block_number()).ok()?, + )); + Some(instance) + } + } + + /// Create a new EthersDB instance, with a provider and a block (None for latest) and a runtime. + /// + /// Refer to [tokio::runtime::Builder] how to create a runtime if you are in synchronous world. + /// If you are already using something like [tokio::main], call EthersDB::new instead. + pub fn with_runtime( + client: Arc, + block_number: Option, + runtime: Runtime, + ) -> Option { + let rt = HandleOrRuntime::Runtime(runtime); + let mut instance = Self { + client, + block_number, + rt, }; - Some(Self { + instance.block_number = Some(BlockId::from( + instance.block_on(instance.client.get_block_number()).ok()?, + )); + Some(instance) + } + + /// Create a new EthersDB instance, with a provider and a block (None for latest) and a handle. + /// + /// This generally allows you to pass any valid runtime handle, refer to [tokio::runtime::Handle] on how + /// to obtain a handle. If you are already in asynchronous world, like [tokio::main], use EthersDB::new instead. + pub fn with_handle( + client: Arc, + block_number: Option, + handle: Handle, + ) -> Option { + let rt = HandleOrRuntime::Handle(handle); + let mut instance = Self { client, block_number, - }) + rt, + }; + + instance.block_number = Some(BlockId::from( + instance.block_on(instance.client.get_block_number()).ok()?, + )); + Some(instance) } - /// internal utility function to call tokio feature and wait for output + /// Internal utility function to call tokio feature and wait for output #[inline] - fn block_on(f: F) -> F::Output + fn block_on(&self, f: F) -> F::Output where F: core::future::Future + Send, F::Output: Send, { - match Handle::try_current() { - Ok(handle) => match handle.runtime_flavor() { - // This essentially equals to tokio::task::spawn_blocking because tokio doesn't - // allow current_thread runtime to block_in_place - RuntimeFlavor::CurrentThread => std::thread::scope(move |s| { - s.spawn(move || { - Builder::new_current_thread() - .enable_all() - .build() - .unwrap() - .block_on(f) - }) - .join() - .unwrap() - }), - _ => tokio::task::block_in_place(move || handle.block_on(f)), - }, - Err(_) => Builder::new_current_thread() - .enable_all() - .build() - .unwrap() - .block_on(f), - } + self.rt.block_on(f) } /// set block number on which upcoming queries will be based @@ -81,7 +121,7 @@ impl DatabaseRef for EthersDB { let code = self.client.get_code(add, self.block_number); tokio::join!(nonce, balance, code) }; - let (nonce, balance, code) = Self::block_on(f); + let (nonce, balance, code) = self.block_on(f); let balance = U256::from_limbs(balance?.0); let nonce = nonce?.as_u64(); @@ -99,19 +139,14 @@ impl DatabaseRef for EthersDB { let add = eH160::from(address.0 .0); let index = H256::from(index.to_be_bytes()); let slot_value: H256 = - Self::block_on(self.client.get_storage_at(add, index, self.block_number))?; + self.block_on(self.client.get_storage_at(add, index, self.block_number))?; Ok(U256::from_be_bytes(slot_value.to_fixed_bytes())) } - fn block_hash_ref(&self, number: U256) -> Result { - // saturate usize - if number > U256::from(u64::MAX) { - return Ok(KECCAK_EMPTY); - } - // We know number <= u64::MAX so unwrap is safe - let number = eU64::from(u64::try_from(number).unwrap()); + fn block_hash_ref(&self, number: u64) -> Result { + let number = eU64::from(number); let block: Option> = - Self::block_on(self.client.get_block(BlockId::from(number)))?; + self.block_on(self.client.get_block(BlockId::from(number)))?; // If number is given, the block is supposed to be finalized so unwrap is safe too. Ok(B256::new(block.unwrap().hash.unwrap().0)) } @@ -136,7 +171,7 @@ impl Database for EthersDB { } #[inline] - fn block_hash(&mut self, number: U256) -> Result { + fn block_hash(&mut self, number: u64) -> Result { ::block_hash_ref(self, number) } } diff --git a/crates/revm/src/db/in_memory_db.rs b/crates/revm/src/db/in_memory_db.rs index a46e6be9..fb0befed 100644 --- a/crates/revm/src/db/in_memory_db.rs +++ b/crates/revm/src/db/in_memory_db.rs @@ -234,8 +234,8 @@ impl Database for CacheDB { } } - fn block_hash(&mut self, number: U256) -> Result { - match self.block_hashes.entry(number) { + fn block_hash(&mut self, number: u64) -> Result { + match self.block_hashes.entry(U256::from(number)) { Entry::Occupied(entry) => Ok(*entry.get()), Entry::Vacant(entry) => { let hash = self.db.block_hash_ref(number)?; @@ -282,8 +282,8 @@ impl DatabaseRef for CacheDB { } } - fn block_hash_ref(&self, number: U256) -> Result { - match self.block_hashes.get(&number) { + fn block_hash_ref(&self, number: u64) -> Result { + match self.block_hashes.get(&U256::from(number)) { Some(entry) => Ok(*entry), None => self.db.block_hash_ref(number), } @@ -403,7 +403,7 @@ impl Database for BenchmarkDB { } // History related - fn block_hash(&mut self, _number: U256) -> Result { + fn block_hash(&mut self, _number: u64) -> Result { Ok(B256::default()) } } diff --git a/crates/revm/src/db/states/cache.rs b/crates/revm/src/db/states/cache.rs index 63c0160b..5dd6770d 100644 --- a/crates/revm/src/db/states/cache.rs +++ b/crates/revm/src/db/states/cache.rs @@ -14,10 +14,10 @@ use std::vec::Vec; /// It generates transitions that is used to build BundleState. #[derive(Clone, Debug, PartialEq, Eq)] pub struct CacheState { - /// Block state account with account state + /// Block state account with account state. pub accounts: HashMap, - /// created contracts - /// TODO add bytecode counter for number of bytecodes added/removed. + /// Created contracts. + // TODO add bytecode counter for number of bytecodes added/removed. pub contracts: HashMap, /// Has EIP-161 state clear enabled (Spurious Dragon hardfork). pub has_state_clear: bool, diff --git a/crates/revm/src/db/states/state.rs b/crates/revm/src/db/states/state.rs index 2b63b7ab..b3f35891 100644 --- a/crates/revm/src/db/states/state.rs +++ b/crates/revm/src/db/states/state.rs @@ -268,16 +268,14 @@ impl Database for State { } } - fn block_hash(&mut self, number: U256) -> Result { - // block number is never bigger then u64::MAX. - let u64num: u64 = number.to(); - match self.block_hashes.entry(u64num) { + fn block_hash(&mut self, number: u64) -> Result { + match self.block_hashes.entry(number) { btree_map::Entry::Occupied(entry) => Ok(*entry.get()), btree_map::Entry::Vacant(entry) => { let ret = *entry.insert(self.database.block_hash(number)?); // prune all hashes that are older then BLOCK_HASH_HISTORY - let last_block = u64num.saturating_sub(BLOCK_HASH_HISTORY as u64); + let last_block = number.saturating_sub(BLOCK_HASH_HISTORY as u64); while let Some(entry) = self.block_hashes.first_entry() { if *entry.key() < last_block { entry.remove(); @@ -311,8 +309,8 @@ mod tests { #[test] fn block_hash_cache() { let mut state = State::builder().build(); - state.block_hash(U256::from(1)).unwrap(); - state.block_hash(U256::from(2)).unwrap(); + state.block_hash(1u64).unwrap(); + state.block_hash(2u64).unwrap(); let test_number = BLOCK_HASH_HISTORY as u64 + 2; @@ -325,7 +323,7 @@ mod tests { BTreeMap::from([(1, block1_hash), (2, block2_hash)]) ); - state.block_hash(U256::from(test_number)).unwrap(); + state.block_hash(test_number).unwrap(); assert_eq!( state.block_hashes, BTreeMap::from([(test_number, block_test_hash), (2, block2_hash)]) diff --git a/crates/revm/src/db/utils.rs b/crates/revm/src/db/utils.rs new file mode 100644 index 00000000..bf069406 --- /dev/null +++ b/crates/revm/src/db/utils.rs @@ -0,0 +1,22 @@ +use tokio::runtime::{Handle, Runtime}; + +// Hold a tokio runtime handle or full runtime +#[derive(Debug)] +pub(crate) enum HandleOrRuntime { + Handle(Handle), + Runtime(Runtime), +} + +impl HandleOrRuntime { + #[inline] + pub(crate) fn block_on(&self, f: F) -> F::Output + where + F: std::future::Future + Send, + F::Output: Send, + { + match self { + Self::Handle(handle) => tokio::task::block_in_place(move || handle.block_on(f)), + Self::Runtime(rt) => rt.block_on(f), + } + } +} diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 9c67a8e9..a7ceec6b 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -7,7 +7,7 @@ use crate::{ }, primitives::{ specification::SpecId, BlockEnv, CfgEnv, EVMError, EVMResult, EnvWithHandlerCfg, - ExecutionResult, HandlerCfg, ResultAndState, TxEnv, TxKind, + ExecutionResult, HandlerCfg, ResultAndState, TxEnv, TxKind, EOF_MAGIC_BYTES, }, Context, ContextWithHandlerCfg, Frame, FrameOrResult, FrameResult, }; @@ -350,13 +350,7 @@ impl Evm<'_, EXT, DB> { TxKind::Create => { // if first byte of data is magic 0xEF00, then it is EOFCreate. if spec_id.is_enabled_in(SpecId::PRAGUE_EOF) - && ctx - .env() - .tx - .data - .get(0..2) - .filter(|&t| t == [0xEF, 00]) - .is_some() + && ctx.env().tx.data.get(0..2) == Some(&EOF_MAGIC_BYTES) { exec.eofcreate( ctx, diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 928d1735..89094d77 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -231,7 +231,6 @@ mod tests { assert_eq!(gas.refunded(), 0); } - // TODO #[test] fn test_consume_gas_with_refund() { let mut return_gas = Gas::new(90); diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index 0e5cb4e1..9e02234b 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -1,7 +1,8 @@ use crate::{ interpreter::{Gas, SuccessOrHalt}, primitives::{ - db::Database, EVMError, ExecutionResult, ResultAndState, Spec, SpecId::LONDON, U256, + db::Database, EVMError, ExecutionResult, ResultAndState, Spec, SpecId::LONDON, + KECCAK_EMPTY, U256, }, Context, FrameResult, }; @@ -21,6 +22,9 @@ pub fn clear(context: &mut Context) { // clear error and journaled state. let _ = context.evm.take_error(); context.evm.inner.journaled_state.clear(); + // Clear valid authorizations after each transaction. + // If transaction is valid they are consumed in `output` handler. + context.evm.inner.valid_authorizations.clear(); } /// Reward beneficiary with gas fee. @@ -92,7 +96,17 @@ pub fn output( let instruction_result = result.into_interpreter_result(); // reset journal and return present state. - let (state, logs) = context.evm.journaled_state.finalize(); + let (mut state, logs) = context.evm.journaled_state.finalize(); + + // clear code of authorized accounts. + for authorized in core::mem::take(&mut context.evm.inner.valid_authorizations).into_iter() { + let account = state + .get_mut(&authorized) + .expect("Authorized account must exist"); + account.info.code = None; + account.info.code_hash = KECCAK_EMPTY; + account.storage.clear(); + } let result = match instruction_result.result.into() { SuccessOrHalt::Success(reason) => ExecutionResult::Success { diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 3cc1d89a..75bb2d45 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -8,10 +8,11 @@ use crate::{ db::Database, Account, EVMError, Env, Spec, SpecId::{CANCUN, PRAGUE, SHANGHAI}, - TxKind, BLOCKHASH_STORAGE_ADDRESS, U256, + TxKind, BLOCKHASH_STORAGE_ADDRESS, KECCAK_EMPTY, U256, }, Context, ContextPrecompiles, }; +use std::vec::Vec; /// Main precompile load #[inline] @@ -32,7 +33,7 @@ pub fn load_accounts( if SPEC::enabled(SHANGHAI) { context.evm.inner.journaled_state.initial_account_load( context.evm.inner.env.block.coinbase, - &[], + [], &mut context.evm.inner.db, )?; } @@ -42,11 +43,79 @@ pub fn load_accounts( if SPEC::enabled(PRAGUE) { context.evm.inner.journaled_state.initial_account_load( BLOCKHASH_STORAGE_ADDRESS, - &[], + [], &mut context.evm.inner.db, )?; } + // EIP-7702. Load bytecode to authorized accounts. + if SPEC::enabled(PRAGUE) { + if let Some(authorization_list) = context.evm.inner.env.tx.authorization_list.as_ref() { + let mut valid_auths = Vec::with_capacity(authorization_list.len()); + for authorization in authorization_list.recovered_iter() { + // 1. recover authority and authorized addresses. + let Some(authority) = authorization.authority() else { + continue; + }; + + // 2. Verify the chain id is either 0 or the chain's current ID. + if authorization.chain_id() != 0 + && authorization.chain_id() != context.evm.inner.env.cfg.chain_id + { + continue; + } + + // warm authority account and check nonce. + let (authority_acc, _) = context + .evm + .inner + .journaled_state + .load_account(authority, &mut context.evm.inner.db)?; + + // 3. Verify that the code of authority is empty. + // In case of multiple same authorities this step will skip loading of + // authorized account. + if authority_acc.info.code_hash() != KECCAK_EMPTY { + continue; + } + + // 4. If nonce list item is length one, verify the nonce of authority is equal to nonce. + if let Some(nonce) = authorization.nonce() { + if nonce != authority_acc.info.nonce { + continue; + } + } + + // warm code account and get the code. + // 6. Add the authority account to accessed_addresses + let (account, _) = context + .evm + .inner + .journaled_state + .load_code(authority, &mut context.evm.inner.db)?; + let code = account.info.code.clone(); + let code_hash = account.info.code_hash; + + // If code is empty no need to set code or add it to valid + // authorizations, as it is a noop operation. + if code_hash == KECCAK_EMPTY { + continue; + } + + // 5. Set the code of authority to code associated with address. + context.evm.inner.journaled_state.set_code_with_hash( + authority, + code.unwrap_or_default(), + code_hash, + ); + + valid_auths.push(authority); + } + + context.evm.inner.valid_authorizations = valid_auths; + } + } + context.evm.load_access_list()?; Ok(()) } diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index 176e0e82..f8840de4 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -42,9 +42,20 @@ pub fn validate_initial_tx_gas( let input = &env.tx.data; let is_create = env.tx.transact_to.is_create(); let access_list = &env.tx.access_list; + let authorization_list_num = env + .tx + .authorization_list + .as_ref() + .map(|l| l.len() as u64) + .unwrap_or_default(); - let initial_gas_spend = - gas::validate_initial_tx_gas(SPEC::SPEC_ID, input, is_create, access_list); + let initial_gas_spend = gas::validate_initial_tx_gas( + SPEC::SPEC_ID, + input, + is_create, + access_list, + authorization_list_num, + ); // Additional check to see if limit is big enough to cover initial gas. if initial_gas_spend > env.tx.gas_limit { diff --git a/crates/revm/src/journaled_state.rs b/crates/revm/src/journaled_state.rs index 6ed29e8b..6ab8c985 100644 --- a/crates/revm/src/journaled_state.rs +++ b/crates/revm/src/journaled_state.rs @@ -1,11 +1,12 @@ -use crate::interpreter::{InstructionResult, SelfDestructResult}; -use crate::primitives::{ - db::Database, hash_map::Entry, Account, Address, Bytecode, EVMError, EvmState, EvmStorageSlot, - HashMap, HashSet, Log, SpecId::*, TransientStorage, KECCAK_EMPTY, PRECOMPILE3, U256, +use crate::{ + interpreter::{InstructionResult, LoadAccountResult, SStoreResult, SelfDestructResult}, + primitives::{ + db::Database, hash_map::Entry, Account, Address, Bytecode, EVMError, EvmState, + EvmStorageSlot, HashMap, HashSet, Log, SpecId, SpecId::*, TransientStorage, B256, + KECCAK_EMPTY, PRECOMPILE3, U256, + }, }; use core::mem; -use revm_interpreter::primitives::SpecId; -use revm_interpreter::{LoadAccountResult, SStoreResult}; use std::vec::Vec; /// JournalState is internal EVM state that is used to contain state and track changes to that state. @@ -142,10 +143,11 @@ impl JournaledState { self.depth as u64 } - /// use it only if you know that acc is warm - /// Assume account is warm + /// Set code and its hash to the account. + /// + /// Note: Assume account is warm and that hash is calculated from code. #[inline] - pub fn set_code(&mut self, address: Address, code: Bytecode) { + pub fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256) { let account = self.state.get_mut(&address).unwrap(); Self::touch_account(self.journal.last_mut().unwrap(), &address, account); @@ -154,10 +156,18 @@ impl JournaledState { .unwrap() .push(JournalEntry::CodeChange { address }); - account.info.code_hash = code.hash_slow(); + account.info.code_hash = hash; account.info.code = Some(code); } + /// use it only if you know that acc is warm + /// Assume account is warm + #[inline] + pub fn set_code(&mut self, address: Address, code: Bytecode) { + let hash = code.hash_slow(); + self.set_code_with_hash(address, code, hash) + } + #[inline] pub fn inc_nonce(&mut self, address: Address) -> Option { let account = self.state.get_mut(&address).unwrap(); @@ -530,7 +540,7 @@ impl JournaledState { pub fn initial_account_load( &mut self, address: Address, - slots: &[U256], + storage_keys: impl IntoIterator, db: &mut DB, ) -> Result<&mut Account, EVMError> { // load or get account. @@ -544,9 +554,11 @@ impl JournaledState { ), }; // preload storages. - for slot in slots { - if let Entry::Vacant(entry) = account.storage.entry(*slot) { - let storage = db.storage(address, *slot).map_err(EVMError::Database)?; + for storage_key in storage_keys.into_iter() { + if let Entry::Vacant(entry) = account.storage.entry(storage_key) { + let storage = db + .storage(address, storage_key) + .map_err(EVMError::Database)?; entry.insert(EvmStorageSlot::new(storage)); } } diff --git a/examples/generate_block_traces.rs b/examples/generate_block_traces.rs index 59d9d036..c3cba6ff 100644 --- a/examples/generate_block_traces.rs +++ b/examples/generate_block_traces.rs @@ -6,7 +6,7 @@ use ethers_providers::{Http, Provider}; use indicatif::ProgressBar; use revm::db::{CacheDB, EthersDB, StateBuilder}; use revm::inspectors::TracerEip3155; -use revm::primitives::{Address, TxKind, U256}; +use revm::primitives::{AccessListItem, Address, TxKind, B256, U256}; use revm::{inspector_handle_register, Evm}; use std::fs::OpenOptions; use std::io::BufWriter; @@ -130,12 +130,16 @@ async fn main() -> anyhow::Result<()> { .0 .into_iter() .map(|item| { - let new_keys: Vec = item + let storage_keys: Vec = item .storage_keys .into_iter() - .map(|h256| U256::from_le_bytes(h256.0)) + .map(|h256| B256::new(h256.0)) .collect(); - (Address::from(item.address.as_fixed_bytes()), new_keys) + + AccessListItem { + address: Address::new(item.address.0), + storage_keys, + } }) .collect(); } else {