diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a0bf2400..03801a49 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,16 +5,21 @@ on: branches: [ "main" ] pull_request: -env: - CARGO_TERM_COLOR: always - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - RISC0_VERSION: 0.20.1 - RISC0_TOOLCHAIN_VERSION: test-release-2 - concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true +# this is needed to gain access via OIDC to the S3 bucket for caching +permissions: + id-token: write + contents: read + +env: + CARGO_TERM_COLOR: always + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + RISC0_VERSION: "^0.21" + RISC0_TOOLCHAIN_VERSION: v2024-02-08.1 + jobs: test: name: test @@ -24,12 +29,9 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive - - uses: risc0/risc0/.github/actions/rustup@release-0.19 - - uses: risc0/risc0/.github/actions/sccache@release-0.19 - - uses: risc0/cargo-install@v1 - with: - crate: cargo-binstall - - run: cargo binstall -y --force cargo-risczero@${{ env.RISC0_VERSION }} + - uses: risc0/risc0/.github/actions/rustup@release-0.21 + - uses: risc0/risc0/.github/actions/sccache@release-0.21 + - run: cargo install --force --locked cargo-risczero@$RISC0_VERSION - run: cargo risczero install --version $RISC0_TOOLCHAIN_VERSION - run: cargo test --workspace --all-targets -F ef-tests,debug-guest-build @@ -39,8 +41,8 @@ jobs: timeout-minutes: 30 steps: - uses: actions/checkout@v4 - - uses: risc0/risc0/.github/actions/rustup@release-0.19 - - uses: risc0/risc0/.github/actions/sccache@release-0.19 + - uses: risc0/risc0/.github/actions/rustup@release-0.21 + - uses: risc0/risc0/.github/actions/sccache@release-0.21 - uses: risc0/clippy-action@main with: reporter: 'github-pr-check' @@ -53,5 +55,5 @@ jobs: timeout-minutes: 10 steps: - uses: actions/checkout@v4 - - uses: risc0/risc0/.github/actions/rustup@release-0.19 + - uses: risc0/risc0/.github/actions/rustup@release-0.21 - run: cargo fmt --all --check diff --git a/.vscode/settings.json b/.vscode/settings.json index 1f1695e6..d24fa80f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,7 @@ "rust-analyzer.cargo.features": "all", "rust-analyzer.linkedProjects": [ "./Cargo.toml", + "./host/Cargo.toml", "./guests/eth-block/Cargo.toml", "./guests/op-block/Cargo.toml", "./guests/op-compose/Cargo.toml", diff --git a/Cargo.lock b/Cargo.lock index ad5e3d27..afb23ea5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -77,11 +77,59 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "async-trait", + "futures-utils-wasm", + "serde", + "thiserror", +] + [[package]] name = "alloy-primitives" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" +checksum = "600d34d8de81e23b6d909c094e23b3d357e01ca36b78a8c5424c501eedbe86f0" dependencies = [ "alloy-rlp", "bytes", @@ -105,6 +153,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", ] @@ -120,11 +169,48 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + [[package]] name = "alloy-sol-macro" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" +checksum = "e86ec0a47740b20bc5613b8712d0d321d031c4efc58e9645af96085d5cccfc27" dependencies = [ "const-hex", "dunce", @@ -140,9 +226,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" +checksum = "ad09ec5853fa700d12d778ad224dcdec636af424d29fad84fb9a2f16a5b0ef09" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -508,9 +594,9 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", @@ -603,9 +689,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -661,11 +747,12 @@ dependencies = [ [[package]] name = "bonsai-sdk" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f0a6b186dce8b2f945bd3ecc5d35a36280400200ed57878c7c3f2aeb01632e" +checksum = "9e0f26687ed447c77b1a40a3665bf88e8327b6de65a74f521544bd225982f589" dependencies = [ "reqwest", + "risc0-groth16", "serde", "thiserror", "tokio", @@ -731,9 +818,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d8c306be83ec04bf5f73710badd8edf56dea23f2f0d8b7f9fe4644d371c758" +checksum = "3130f3d8717cc02e668a896af24984d5d5d4e8bf12e278e982e0f1bd88a0f9af" dependencies = [ "blst", "cc", @@ -1188,6 +1275,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.16.9" @@ -1244,9 +1337,9 @@ dependencies = [ [[package]] name = "enr" -version = "0.9.1" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe81b5c06ecfdbc71dd845216f225f53b62a10cb8a16c946836a3467f701d05b" +checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" dependencies = [ "base64 0.21.7", "bytes", @@ -1283,9 +1376,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05e7cf40684ae96ade6232ed84582f40ce0a66efcd43a5117aef610534f8e0b8" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" dependencies = [ "anstream", "anstyle", @@ -1426,9 +1519,9 @@ dependencies = [ [[package]] name = "ethers-core" -version = "2.0.13" +version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aab3cef6cc1c9fd7f787043c81ad3052eff2b96a3878ef1526aa446311bdbfc9" +checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" dependencies = [ "arrayvec", "bytes", @@ -1456,9 +1549,9 @@ dependencies = [ [[package]] name = "ethers-providers" -version = "2.0.13" +version = "2.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb6b15393996e3b8a78ef1332d6483c11d839042c17be58decc92fa8b1c3508a" +checksum = "6434c9a33891f1effc9c75472e12666db2fa5a0fec4b29af6221680a6fe83ab2" dependencies = [ "async-trait", "auto_impl", @@ -1738,6 +1831,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxhash" version = "0.2.1" @@ -2135,6 +2234,15 @@ 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 = "itoa" version = "1.0.10" @@ -2280,7 +2388,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "redox_syscall", ] @@ -2303,9 +2411,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "malloc_buf" @@ -2888,7 +2996,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.2", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", @@ -3147,12 +3255,13 @@ dependencies = [ [[package]] name = "revm" -version = "5.0.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f86bdefa6dac07d92e2f5c37d7d183f2575b2f9e0ee9cba9402dfde912524" +checksum = "24fd3ed4b62dc61c647552d8b781811ae25ec74d23309055077e4dfb392444d2" dependencies = [ "auto_impl", "cfg-if", + "dyn-clone", "revm-interpreter", "revm-precompile", "serde", @@ -3161,9 +3270,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "2.1.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a80b516cc706630e604e2fd47c281501d2fb222712be4328921361388b7d2df" +checksum = "9f0a1818f8c876b0d71a0714217c34da7df8a42c0462750768779d55680e4554" dependencies = [ "revm-primitives", "serde", @@ -3171,9 +3280,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "4.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6912fafe7f70a264ec5895875ce2f2d0621a39263844280c9ee7f85e35bbb9e" +checksum = "7a9645a70f1df1e5bd7fa8718b9ba486fac9c3f0467aa6b58e7f590d5f6fd0f7" dependencies = [ "aurora-engine-modexp", "c-kzg", @@ -3188,16 +3297,17 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b3683a40f1e94e7389c8e81e5f26bb5d30875ed0b48ab07985ec32eb6d6c712" +checksum = "323ad597cf75ac9cb1d161be29fcc3562426f0278a1d04741697fca556e1ceea" dependencies = [ "alloy-primitives", "auto_impl", - "bitflags 2.4.2", + "bitflags 2.5.0", "bitvec", "c-kzg", "cfg-if", + "dyn-clone", "enumn", "hashbrown 0.14.3", "hex", @@ -3254,9 +3364,9 @@ dependencies = [ [[package]] name = "risc0-binfmt" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d263c6370d7714d2a634b6d88deb3871d0fad1f9486a9da6d48139c1ac85b26" +checksum = "2ae2939426c60756f910352184716a3538748208c9e11ade4a507db3b2757157" dependencies = [ "anyhow", "elf", @@ -3268,9 +3378,9 @@ dependencies = [ [[package]] name = "risc0-build" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a636849a58335ebece68161006a53d5590a6698092c3ca8e8a40a7c0aa8a20fb" +checksum = "d7a6a0138c9ae1d82eaa2ab6047535481a17641ba6c354890770bf94fbef8049" dependencies = [ "anyhow", "cargo-platform", @@ -3286,9 +3396,9 @@ dependencies = [ [[package]] name = "risc0-build-kernel" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fa4cd0e10797e933d0e2056e24e5b15cc0bb324d5dfd44e145048a0029f7af5" +checksum = "cc02fece98f870221c25c22241e5f226fb3a9230df9cdeab170907440a97f41b" dependencies = [ "cc", "directories", @@ -3299,9 +3409,9 @@ dependencies = [ [[package]] name = "risc0-circuit-recursion" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9835069929a0e7b6b4b34e6a83f08aaa9d34b30023b9ccaf96ddbe20404eba" +checksum = "a43cade35f73ad81ba974fe1d5e1513331f87052af8377b26b00a838f39c6920" dependencies = [ "anyhow", "bytemuck", @@ -3320,9 +3430,9 @@ dependencies = [ [[package]] name = "risc0-circuit-recursion-sys" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b12fa422928ccae0ca6d39a3bdb784e417c65813f004b258f2113609095358ba" +checksum = "6ad2b82cbb0e0cc22182f00287f513daea3ea8a5cc0b709d8afdd9d9180fb89a" dependencies = [ "glob", "risc0-build-kernel", @@ -3331,9 +3441,9 @@ dependencies = [ [[package]] name = "risc0-circuit-rv32im" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb1caa759ab74d08779e062fcf98f5bd34397dfde572516a52369f0ec46db650" +checksum = "31440989146b342a7d37c15079c9568c69b7f988f3b789f422c7d4ed76526ddb" dependencies = [ "anyhow", "metal", @@ -3348,9 +3458,9 @@ dependencies = [ [[package]] name = "risc0-circuit-rv32im-sys" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a88e4b25e30eeb49adab83fe014110bec18e69dd63a47a5f36b00ac48fe373" +checksum = "634d60a79888ec9416dbd3c88bac9b630b05e513c466b7acd64b7641eed48749" dependencies = [ "glob", "risc0-build-kernel", @@ -3359,19 +3469,42 @@ dependencies = [ [[package]] name = "risc0-core" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be79c89bcd18886b376073e3da22f8b7963247a42dce7b49cf3d09853f51641e" +checksum = "02e0cbd09d03c23b572b66cd96a56143adb22bf895aca89c1a153ccebedaa0b4" dependencies = [ "bytemuck", "rand_core", ] +[[package]] +name = "risc0-groth16" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1e9b8dae3f9c3862b6278b2812989a2f5a537975e5bd6a687f07cf1df68a36" +dependencies = [ + "anyhow", + "ark-bn254", + "ark-groth16", + "ark-serialize 0.4.2", + "bytemuck", + "hex", + "num-bigint 0.4.4", + "num-derive", + "num-traits", + "risc0-core", + "risc0-zkp", + "serde", + "serde_json", + "tempfile", + "tracing", +] + [[package]] name = "risc0-sys" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c40caeacec542a0187e44203dd90501edcecf194cad648d590f6b2b0e4e4e5b" +checksum = "61168816f4921e3cf1c9ff98792a7aa58d3e6c2dc5072bd7666690310e99fea1" dependencies = [ "cc", "risc0-build-kernel", @@ -3379,9 +3512,9 @@ dependencies = [ [[package]] name = "risc0-zkp" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e20a57e04840a5afadebb5d232546245f4fd8bd0e774bd69bf4bf25f8ab90c04" +checksum = "b96b035f744ecaaa7e9809c699bc85cf669cbab6f297f141d918e9b4c8098b79" dependencies = [ "anyhow", "blake2", @@ -3406,15 +3539,12 @@ dependencies = [ [[package]] name = "risc0-zkvm" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922588cb4b884b3951316a65581ccdfd1174af93c54093190878366812073329" +checksum = "2a1275834c86176efc122a172c2b5f271a8a5d792de7efbc47dfbecaaaff9432" dependencies = [ "addr2line", "anyhow", - "ark-bn254", - "ark-groth16", - "ark-serialize 0.4.2", "bincode", "bonsai-sdk", "bytemuck", @@ -3426,7 +3556,6 @@ dependencies = [ "hex", "human-repr", "lazy-regex", - "num-bigint 0.4.4", "num-derive", "num-traits", "prost", @@ -3437,6 +3566,7 @@ dependencies = [ "risc0-circuit-recursion", "risc0-circuit-rv32im", "risc0-core", + "risc0-groth16", "risc0-zkp", "risc0-zkvm-platform", "rrs-lib", @@ -3451,9 +3581,9 @@ dependencies = [ [[package]] name = "risc0-zkvm-platform" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5819c0c3bfd8f20b1226c9d4ca1f342eb3d8385e71211a9383a879643d1dde" +checksum = "03b6378c9e407be18a1560ed030fd87fb6056293c56263efac46c507ae97e0d7" dependencies = [ "bytemuck", "getrandom", @@ -3593,7 +3723,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -3735,6 +3865,7 @@ version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ + "rand", "secp256k1-sys", ] @@ -3841,9 +3972,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d167997bd841ec232f5b2b8e0e26606df2e7caa4c31b95ea9ca52b200bd270" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" dependencies = [ "base64 0.21.7", "chrono", @@ -3859,9 +3990,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.6.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "865f9743393e638991566a8b7a479043c2c8da94a33e0a31f18214c9cae0a64d" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" dependencies = [ "darling", "proc-macro2", @@ -3882,9 +4013,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -4015,18 +4146,18 @@ checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "strum" -version = "0.25.0" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.25.3" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" dependencies = [ "heck", "proc-macro2", @@ -4078,9 +4209,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" +checksum = "cb3d0961cd53c23ea94eeec56ba940f636f6394788976e9f16ca5ee0aca7464a" dependencies = [ "paste", "proc-macro2", @@ -4990,10 +5121,8 @@ dependencies = [ "risc0-zkvm", "rstest", "serde", - "tempfile", "tokio", "tracing", - "typetag", "zeth-guests", "zeth-lib", "zeth-primitives", @@ -5039,6 +5168,9 @@ dependencies = [ name = "zeth-primitives" version = "0.1.0" dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rlp-derive", @@ -5047,12 +5179,11 @@ dependencies = [ "bytes", "ethers-core", "hex-literal", - "k256", "log", - "revm-primitives", "rlp", "serde", "serde_json", + "serde_with", "sha2", "sha3", "thiserror", diff --git a/Cargo.toml b/Cargo.toml index 0d14f14d..e9695a2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,12 +17,12 @@ lto = true opt-level = 3 [workspace.dependencies] -bonsai-sdk = { version = "0.6.0", features = ["async"] } +bonsai-sdk = { version = "0.7.0", features = ["async"] } hashbrown = { version = "0.14.3", features = ["inline-more"] } -risc0-build = { version = "0.20.1" } -risc0-zkvm = { version = "0.20.1", default-features = false } -revm-primitives = { version = "2.0", default_features = false } -revm = { version = "5.0", default-features = false, features = [ +risc0-build = { version = "0.21.0" } +risc0-zkvm = { version = "0.21.0", default-features = false } +revm-primitives = { version = "3.1", default_features = false } +revm = { version = "7.2", default-features = false, features = [ "std", "serde", "optimism", diff --git a/guests/build.rs b/guests/build.rs index e540a42d..affe663a 100644 --- a/guests/build.rs +++ b/guests/build.rs @@ -36,5 +36,5 @@ fn main() { #[cfg(any(feature = "debug-guest-build", debug_assertions))] fn main() { - risc0_build::embed_methods() + risc0_build::embed_methods(); } diff --git a/guests/eth-block/Cargo.lock b/guests/eth-block/Cargo.lock index 7221c80a..e824a772 100644 --- a/guests/eth-block/Cargo.lock +++ b/guests/eth-block/Cargo.lock @@ -50,11 +50,59 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "async-trait", + "futures-utils-wasm", + "serde", + "thiserror", +] + [[package]] name = "alloy-primitives" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" +checksum = "600d34d8de81e23b6d909c094e23b3d357e01ca36b78a8c5424c501eedbe86f0" dependencies = [ "alloy-rlp", "bytes", @@ -78,6 +126,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", ] @@ -93,16 +142,53 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + [[package]] name = "alloy-sol-macro" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" +checksum = "e86ec0a47740b20bc5613b8712d0d321d031c4efc58e9645af96085d5cccfc27" dependencies = [ "const-hex", "dunce", "heck", - "indexmap", + "indexmap 2.2.3", "proc-macro-error", "proc-macro2", "quote", @@ -113,9 +199,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" +checksum = "ad09ec5853fa700d12d778ad224dcdec636af424d29fad84fb9a2f16a5b0ef09" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -123,6 +209,21 @@ dependencies = [ "serde", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.79" @@ -170,7 +271,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", - "itertools", + "itertools 0.10.5", "num-traits", "zeroize", ] @@ -205,7 +306,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "digest 0.10.7", - "itertools", + "itertools 0.10.5", "num-bigint", "num-traits", "paste", @@ -403,9 +504,9 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", @@ -480,9 +581,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -579,9 +680,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d8c306be83ec04bf5f73710badd8edf56dea23f2f0d8b7f9fe4644d371c758" +checksum = "3130f3d8717cc02e668a896af24984d5d5d4e8bf12e278e982e0f1bd88a0f9af" dependencies = [ "blst", "cc", @@ -609,7 +710,11 @@ version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ + "android-tzdata", + "iana-time-zone", "num-traits", + "serde", + "windows-targets 0.52.0", ] [[package]] @@ -688,8 +793,8 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.2" -source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.2-risczero.0#8b30304277cfe553b51a78a0e693f48bbb059eb3" +version = "0.5.5" +source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.5-risczero.0#3ab63a6f1048833f7047d5a50532e4a4cc789384" dependencies = [ "generic-array", "getrandom", @@ -708,6 +813,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.48", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.48", +] + [[package]] name = "dary_heap" version = "0.3.6" @@ -737,6 +877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -796,6 +937,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.16.9" @@ -1185,6 +1332,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxhash" version = "0.2.1" @@ -1263,13 +1416,19 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 2.2.3", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.13.2" @@ -1407,6 +1566,35 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -1455,6 +1643,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.2.3" @@ -1463,6 +1662,7 @@ checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] @@ -1489,6 +1689,15 @@ 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 = "itoa" version = "1.0.10" @@ -2041,7 +2250,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.2", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", @@ -2194,12 +2403,13 @@ dependencies = [ [[package]] name = "revm" -version = "5.0.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f86bdefa6dac07d92e2f5c37d7d183f2575b2f9e0ee9cba9402dfde912524" +checksum = "24fd3ed4b62dc61c647552d8b781811ae25ec74d23309055077e4dfb392444d2" dependencies = [ "auto_impl", "cfg-if", + "dyn-clone", "revm-interpreter", "revm-precompile", "serde", @@ -2208,9 +2418,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "2.1.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a80b516cc706630e604e2fd47c281501d2fb222712be4328921361388b7d2df" +checksum = "9f0a1818f8c876b0d71a0714217c34da7df8a42c0462750768779d55680e4554" dependencies = [ "revm-primitives", "serde", @@ -2218,9 +2428,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "4.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6912fafe7f70a264ec5895875ce2f2d0621a39263844280c9ee7f85e35bbb9e" +checksum = "7a9645a70f1df1e5bd7fa8718b9ba486fac9c3f0467aa6b58e7f590d5f6fd0f7" dependencies = [ "aurora-engine-modexp", "c-kzg", @@ -2235,16 +2445,17 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b3683a40f1e94e7389c8e81e5f26bb5d30875ed0b48ab07985ec32eb6d6c712" +checksum = "323ad597cf75ac9cb1d161be29fcc3562426f0278a1d04741697fca556e1ceea" dependencies = [ "alloy-primitives", "auto_impl", - "bitflags 2.4.2", + "bitflags 2.5.0", "bitvec", "c-kzg", "cfg-if", + "dyn-clone", "enumn", "hashbrown 0.14.3", "hex", @@ -2301,9 +2512,9 @@ dependencies = [ [[package]] name = "risc0-binfmt" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d263c6370d7714d2a634b6d88deb3871d0fad1f9486a9da6d48139c1ac85b26" +checksum = "2ae2939426c60756f910352184716a3538748208c9e11ade4a507db3b2757157" dependencies = [ "anyhow", "elf", @@ -2315,9 +2526,9 @@ dependencies = [ [[package]] name = "risc0-circuit-recursion" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9835069929a0e7b6b4b34e6a83f08aaa9d34b30023b9ccaf96ddbe20404eba" +checksum = "a43cade35f73ad81ba974fe1d5e1513331f87052af8377b26b00a838f39c6920" dependencies = [ "anyhow", "bytemuck", @@ -2329,9 +2540,9 @@ dependencies = [ [[package]] name = "risc0-circuit-rv32im" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb1caa759ab74d08779e062fcf98f5bd34397dfde572516a52369f0ec46db650" +checksum = "31440989146b342a7d37c15079c9568c69b7f988f3b789f422c7d4ed76526ddb" dependencies = [ "anyhow", "risc0-core", @@ -2342,19 +2553,37 @@ dependencies = [ [[package]] name = "risc0-core" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be79c89bcd18886b376073e3da22f8b7963247a42dce7b49cf3d09853f51641e" +checksum = "02e0cbd09d03c23b572b66cd96a56143adb22bf895aca89c1a153ccebedaa0b4" dependencies = [ "bytemuck", "rand_core", ] +[[package]] +name = "risc0-groth16" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1e9b8dae3f9c3862b6278b2812989a2f5a537975e5bd6a687f07cf1df68a36" +dependencies = [ + "anyhow", + "ark-bn254", + "ark-groth16", + "ark-serialize 0.4.2", + "hex", + "num-bigint", + "num-derive", + "num-traits", + "risc0-zkp", + "serde", +] + [[package]] name = "risc0-zkp" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e20a57e04840a5afadebb5d232546245f4fd8bd0e774bd69bf4bf25f8ab90c04" +checksum = "b96b035f744ecaaa7e9809c699bc85cf669cbab6f297f141d918e9b4c8098b79" dependencies = [ "anyhow", "blake2", @@ -2372,25 +2601,22 @@ dependencies = [ [[package]] name = "risc0-zkvm" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922588cb4b884b3951316a65581ccdfd1174af93c54093190878366812073329" +checksum = "2a1275834c86176efc122a172c2b5f271a8a5d792de7efbc47dfbecaaaff9432" dependencies = [ "anyhow", - "ark-bn254", - "ark-groth16", - "ark-serialize 0.4.2", "bytemuck", "cfg-if", "getrandom", "hex", - "num-bigint", "num-derive", "num-traits", "risc0-binfmt", "risc0-circuit-recursion", "risc0-circuit-rv32im", "risc0-core", + "risc0-groth16", "risc0-zkp", "risc0-zkvm-platform", "rrs-lib", @@ -2402,9 +2628,9 @@ dependencies = [ [[package]] name = "risc0-zkvm-platform" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5819c0c3bfd8f20b1226c9d4ca1f342eb3d8385e71211a9383a879643d1dde" +checksum = "03b6378c9e407be18a1560ed030fd87fb6056293c56263efac46c507ae97e0d7" dependencies = [ "bytemuck", "getrandom", @@ -2515,7 +2741,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -2637,6 +2863,7 @@ version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ + "rand", "secp256k1-sys", ] @@ -2711,7 +2938,7 @@ version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap", + "indexmap 2.2.3", "itoa", "ryu", "serde", @@ -2729,6 +2956,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +dependencies = [ + "base64 0.21.7", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.3", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2742,8 +2999,8 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" -source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2-v0.10.6-risczero.0#7fd6900c4f637bd15ee2642dfa77110f8f1ad065" +version = "0.10.8" +source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2-v0.10.8-risczero.0#244dc3b08788f7a4ccce14c66896ae3b4f24c166" dependencies = [ "cfg-if", "cpufeatures", @@ -2854,6 +3111,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.25.0" @@ -2919,9 +3182,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" +checksum = "cb3d0961cd53c23ea94eeec56ba940f636f6394788976e9f16ca5ee0aca7464a" dependencies = [ "paste", "proc-macro2", @@ -3139,7 +3402,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3150,7 +3413,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3161,7 +3424,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3476,6 +3739,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3717,6 +3989,7 @@ dependencies = [ "ruint", "serde", "serde_json", + "serde_with", "thiserror", "tokio", "zeth-primitives", @@ -3726,17 +3999,19 @@ dependencies = [ name = "zeth-primitives" version = "0.1.0" dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rlp-derive", "anyhow", "bytes", "ethers-core", - "k256", "log", - "revm-primitives", "rlp", "serde", + "serde_with", "sha2", "sha3", "thiserror", diff --git a/guests/eth-block/Cargo.toml b/guests/eth-block/Cargo.toml index 06a1c521..38870b40 100644 --- a/guests/eth-block/Cargo.toml +++ b/guests/eth-block/Cargo.toml @@ -6,14 +6,14 @@ edition = "2021" [workspace] [dependencies] -risc0-zkvm = { version = "0.20.1", default-features = false, features = ['std'] } +risc0-zkvm = { version = "0.21.0", default-features = false, features = ['std'] } zeth-lib = { path = "../../lib", default-features = false } [patch.crates-io] # use optimized risc0 circuit -crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.2-risczero.0" } +crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.3-risczero.0" } -sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.6-risczero.0" } +sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } [profile.release] codegen-units = 1 diff --git a/guests/op-block/Cargo.lock b/guests/op-block/Cargo.lock index e196ed36..7b098d3c 100644 --- a/guests/op-block/Cargo.lock +++ b/guests/op-block/Cargo.lock @@ -50,11 +50,59 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "async-trait", + "futures-utils-wasm", + "serde", + "thiserror", +] + [[package]] name = "alloy-primitives" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" +checksum = "600d34d8de81e23b6d909c094e23b3d357e01ca36b78a8c5424c501eedbe86f0" dependencies = [ "alloy-rlp", "bytes", @@ -78,6 +126,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", ] @@ -93,16 +142,53 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + [[package]] name = "alloy-sol-macro" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" +checksum = "e86ec0a47740b20bc5613b8712d0d321d031c4efc58e9645af96085d5cccfc27" dependencies = [ "const-hex", "dunce", "heck", - "indexmap", + "indexmap 2.2.3", "proc-macro-error", "proc-macro2", "quote", @@ -113,9 +199,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" +checksum = "ad09ec5853fa700d12d778ad224dcdec636af424d29fad84fb9a2f16a5b0ef09" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -123,6 +209,21 @@ dependencies = [ "serde", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.79" @@ -170,7 +271,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", - "itertools", + "itertools 0.10.5", "num-traits", "zeroize", ] @@ -205,7 +306,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "digest 0.10.7", - "itertools", + "itertools 0.10.5", "num-bigint", "num-traits", "paste", @@ -403,9 +504,9 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", @@ -480,9 +581,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -579,9 +680,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d8c306be83ec04bf5f73710badd8edf56dea23f2f0d8b7f9fe4644d371c758" +checksum = "3130f3d8717cc02e668a896af24984d5d5d4e8bf12e278e982e0f1bd88a0f9af" dependencies = [ "blst", "cc", @@ -609,7 +710,11 @@ version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ + "android-tzdata", + "iana-time-zone", "num-traits", + "serde", + "windows-targets 0.52.0", ] [[package]] @@ -688,8 +793,8 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.2" -source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.2-risczero.0#8b30304277cfe553b51a78a0e693f48bbb059eb3" +version = "0.5.5" +source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.5-risczero.0#3ab63a6f1048833f7047d5a50532e4a4cc789384" dependencies = [ "generic-array", "getrandom", @@ -708,6 +813,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.48", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.48", +] + [[package]] name = "dary_heap" version = "0.3.6" @@ -737,6 +877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -796,6 +937,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.16.9" @@ -1177,6 +1324,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxhash" version = "0.2.1" @@ -1255,13 +1408,19 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 2.2.3", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.13.2" @@ -1399,6 +1558,35 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -1447,6 +1635,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.2.3" @@ -1455,6 +1654,7 @@ checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] @@ -1481,6 +1681,15 @@ 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 = "itoa" version = "1.0.10" @@ -2041,7 +2250,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.2", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", @@ -2194,12 +2403,13 @@ dependencies = [ [[package]] name = "revm" -version = "5.0.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f86bdefa6dac07d92e2f5c37d7d183f2575b2f9e0ee9cba9402dfde912524" +checksum = "24fd3ed4b62dc61c647552d8b781811ae25ec74d23309055077e4dfb392444d2" dependencies = [ "auto_impl", "cfg-if", + "dyn-clone", "revm-interpreter", "revm-precompile", "serde", @@ -2208,9 +2418,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "2.1.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a80b516cc706630e604e2fd47c281501d2fb222712be4328921361388b7d2df" +checksum = "9f0a1818f8c876b0d71a0714217c34da7df8a42c0462750768779d55680e4554" dependencies = [ "revm-primitives", "serde", @@ -2218,9 +2428,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "4.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6912fafe7f70a264ec5895875ce2f2d0621a39263844280c9ee7f85e35bbb9e" +checksum = "7a9645a70f1df1e5bd7fa8718b9ba486fac9c3f0467aa6b58e7f590d5f6fd0f7" dependencies = [ "aurora-engine-modexp", "c-kzg", @@ -2235,16 +2445,17 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b3683a40f1e94e7389c8e81e5f26bb5d30875ed0b48ab07985ec32eb6d6c712" +checksum = "323ad597cf75ac9cb1d161be29fcc3562426f0278a1d04741697fca556e1ceea" dependencies = [ "alloy-primitives", "auto_impl", - "bitflags 2.4.2", + "bitflags 2.5.0", "bitvec", "c-kzg", "cfg-if", + "dyn-clone", "enumn", "hashbrown 0.14.3", "hex", @@ -2301,9 +2512,9 @@ dependencies = [ [[package]] name = "risc0-binfmt" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d263c6370d7714d2a634b6d88deb3871d0fad1f9486a9da6d48139c1ac85b26" +checksum = "2ae2939426c60756f910352184716a3538748208c9e11ade4a507db3b2757157" dependencies = [ "anyhow", "elf", @@ -2315,9 +2526,9 @@ dependencies = [ [[package]] name = "risc0-circuit-recursion" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9835069929a0e7b6b4b34e6a83f08aaa9d34b30023b9ccaf96ddbe20404eba" +checksum = "a43cade35f73ad81ba974fe1d5e1513331f87052af8377b26b00a838f39c6920" dependencies = [ "anyhow", "bytemuck", @@ -2329,9 +2540,9 @@ dependencies = [ [[package]] name = "risc0-circuit-rv32im" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb1caa759ab74d08779e062fcf98f5bd34397dfde572516a52369f0ec46db650" +checksum = "31440989146b342a7d37c15079c9568c69b7f988f3b789f422c7d4ed76526ddb" dependencies = [ "anyhow", "risc0-core", @@ -2342,19 +2553,37 @@ dependencies = [ [[package]] name = "risc0-core" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be79c89bcd18886b376073e3da22f8b7963247a42dce7b49cf3d09853f51641e" +checksum = "02e0cbd09d03c23b572b66cd96a56143adb22bf895aca89c1a153ccebedaa0b4" dependencies = [ "bytemuck", "rand_core", ] +[[package]] +name = "risc0-groth16" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1e9b8dae3f9c3862b6278b2812989a2f5a537975e5bd6a687f07cf1df68a36" +dependencies = [ + "anyhow", + "ark-bn254", + "ark-groth16", + "ark-serialize 0.4.2", + "hex", + "num-bigint", + "num-derive", + "num-traits", + "risc0-zkp", + "serde", +] + [[package]] name = "risc0-zkp" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e20a57e04840a5afadebb5d232546245f4fd8bd0e774bd69bf4bf25f8ab90c04" +checksum = "b96b035f744ecaaa7e9809c699bc85cf669cbab6f297f141d918e9b4c8098b79" dependencies = [ "anyhow", "blake2", @@ -2372,25 +2601,22 @@ dependencies = [ [[package]] name = "risc0-zkvm" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922588cb4b884b3951316a65581ccdfd1174af93c54093190878366812073329" +checksum = "2a1275834c86176efc122a172c2b5f271a8a5d792de7efbc47dfbecaaaff9432" dependencies = [ "anyhow", - "ark-bn254", - "ark-groth16", - "ark-serialize 0.4.2", "bytemuck", "cfg-if", "getrandom", "hex", - "num-bigint", "num-derive", "num-traits", "risc0-binfmt", "risc0-circuit-recursion", "risc0-circuit-rv32im", "risc0-core", + "risc0-groth16", "risc0-zkp", "risc0-zkvm-platform", "rrs-lib", @@ -2402,9 +2628,9 @@ dependencies = [ [[package]] name = "risc0-zkvm-platform" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5819c0c3bfd8f20b1226c9d4ca1f342eb3d8385e71211a9383a879643d1dde" +checksum = "03b6378c9e407be18a1560ed030fd87fb6056293c56263efac46c507ae97e0d7" dependencies = [ "bytemuck", "getrandom", @@ -2515,7 +2741,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -2637,6 +2863,7 @@ version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ + "rand", "secp256k1-sys", ] @@ -2711,7 +2938,7 @@ version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap", + "indexmap 2.2.3", "itoa", "ryu", "serde", @@ -2729,6 +2956,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +dependencies = [ + "base64 0.21.7", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.3", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2742,8 +2999,8 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" -source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2-v0.10.6-risczero.0#7fd6900c4f637bd15ee2642dfa77110f8f1ad065" +version = "0.10.8" +source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2-v0.10.8-risczero.0#244dc3b08788f7a4ccce14c66896ae3b4f24c166" dependencies = [ "cfg-if", "cpufeatures", @@ -2854,6 +3111,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.25.0" @@ -2919,9 +3182,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" +checksum = "cb3d0961cd53c23ea94eeec56ba940f636f6394788976e9f16ca5ee0aca7464a" dependencies = [ "paste", "proc-macro2", @@ -3139,7 +3402,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3150,7 +3413,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3161,7 +3424,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3476,6 +3739,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3717,6 +3989,7 @@ dependencies = [ "ruint", "serde", "serde_json", + "serde_with", "thiserror", "tokio", "zeth-primitives", @@ -3726,17 +3999,19 @@ dependencies = [ name = "zeth-primitives" version = "0.1.0" dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rlp-derive", "anyhow", "bytes", "ethers-core", - "k256", "log", - "revm-primitives", "rlp", "serde", + "serde_with", "sha2", "sha3", "thiserror", diff --git a/guests/op-block/Cargo.toml b/guests/op-block/Cargo.toml index e73679d2..c31386f8 100644 --- a/guests/op-block/Cargo.toml +++ b/guests/op-block/Cargo.toml @@ -6,14 +6,14 @@ edition = "2021" [workspace] [dependencies] -risc0-zkvm = { version = "0.20.1", default-features = false, features = ['std'] } +risc0-zkvm = { version = "0.21.0", default-features = false, features = ['std'] } zeth-lib = { path = "../../lib", default-features = false } [patch.crates-io] # use optimized risc0 circuit -crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.2-risczero.0" } +crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.3-risczero.0" } -sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.6-risczero.0" } +sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } [profile.release] codegen-units = 1 diff --git a/guests/op-compose/Cargo.lock b/guests/op-compose/Cargo.lock index 708b2473..a89168cd 100644 --- a/guests/op-compose/Cargo.lock +++ b/guests/op-compose/Cargo.lock @@ -50,11 +50,59 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "async-trait", + "futures-utils-wasm", + "serde", + "thiserror", +] + [[package]] name = "alloy-primitives" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" +checksum = "600d34d8de81e23b6d909c094e23b3d357e01ca36b78a8c5424c501eedbe86f0" dependencies = [ "alloy-rlp", "bytes", @@ -78,6 +126,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", ] @@ -93,16 +142,53 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + [[package]] name = "alloy-sol-macro" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" +checksum = "e86ec0a47740b20bc5613b8712d0d321d031c4efc58e9645af96085d5cccfc27" dependencies = [ "const-hex", "dunce", "heck", - "indexmap", + "indexmap 2.2.3", "proc-macro-error", "proc-macro2", "quote", @@ -113,9 +199,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" +checksum = "ad09ec5853fa700d12d778ad224dcdec636af424d29fad84fb9a2f16a5b0ef09" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -123,6 +209,21 @@ dependencies = [ "serde", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.79" @@ -170,7 +271,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", - "itertools", + "itertools 0.10.5", "num-traits", "zeroize", ] @@ -205,7 +306,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "digest 0.10.7", - "itertools", + "itertools 0.10.5", "num-bigint", "num-traits", "paste", @@ -403,9 +504,9 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", @@ -480,9 +581,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -579,9 +680,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d8c306be83ec04bf5f73710badd8edf56dea23f2f0d8b7f9fe4644d371c758" +checksum = "3130f3d8717cc02e668a896af24984d5d5d4e8bf12e278e982e0f1bd88a0f9af" dependencies = [ "blst", "cc", @@ -609,7 +710,11 @@ version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ + "android-tzdata", + "iana-time-zone", "num-traits", + "serde", + "windows-targets 0.52.0", ] [[package]] @@ -688,8 +793,8 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.2" -source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.2-risc0#8b30304277cfe553b51a78a0e693f48bbb059eb3" +version = "0.5.5" +source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.5-risczero.0#3ab63a6f1048833f7047d5a50532e4a4cc789384" dependencies = [ "generic-array", "getrandom", @@ -708,6 +813,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.48", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.48", +] + [[package]] name = "dary_heap" version = "0.3.6" @@ -737,6 +877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -796,6 +937,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.16.9" @@ -1177,6 +1324,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxhash" version = "0.2.1" @@ -1255,13 +1408,19 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 2.2.3", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.13.2" @@ -1399,6 +1558,35 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -1447,6 +1635,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.2.3" @@ -1455,6 +1654,7 @@ checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] @@ -1481,6 +1681,15 @@ 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 = "itoa" version = "1.0.10" @@ -2041,7 +2250,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.2", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", @@ -2194,12 +2403,13 @@ dependencies = [ [[package]] name = "revm" -version = "5.0.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f86bdefa6dac07d92e2f5c37d7d183f2575b2f9e0ee9cba9402dfde912524" +checksum = "24fd3ed4b62dc61c647552d8b781811ae25ec74d23309055077e4dfb392444d2" dependencies = [ "auto_impl", "cfg-if", + "dyn-clone", "revm-interpreter", "revm-precompile", "serde", @@ -2208,9 +2418,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "2.1.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a80b516cc706630e604e2fd47c281501d2fb222712be4328921361388b7d2df" +checksum = "9f0a1818f8c876b0d71a0714217c34da7df8a42c0462750768779d55680e4554" dependencies = [ "revm-primitives", "serde", @@ -2218,9 +2428,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "4.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6912fafe7f70a264ec5895875ce2f2d0621a39263844280c9ee7f85e35bbb9e" +checksum = "7a9645a70f1df1e5bd7fa8718b9ba486fac9c3f0467aa6b58e7f590d5f6fd0f7" dependencies = [ "aurora-engine-modexp", "c-kzg", @@ -2235,16 +2445,17 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b3683a40f1e94e7389c8e81e5f26bb5d30875ed0b48ab07985ec32eb6d6c712" +checksum = "323ad597cf75ac9cb1d161be29fcc3562426f0278a1d04741697fca556e1ceea" dependencies = [ "alloy-primitives", "auto_impl", - "bitflags 2.4.2", + "bitflags 2.5.0", "bitvec", "c-kzg", "cfg-if", + "dyn-clone", "enumn", "hashbrown 0.14.3", "hex", @@ -2301,9 +2512,9 @@ dependencies = [ [[package]] name = "risc0-binfmt" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d263c6370d7714d2a634b6d88deb3871d0fad1f9486a9da6d48139c1ac85b26" +checksum = "2ae2939426c60756f910352184716a3538748208c9e11ade4a507db3b2757157" dependencies = [ "anyhow", "elf", @@ -2315,9 +2526,9 @@ dependencies = [ [[package]] name = "risc0-circuit-recursion" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9835069929a0e7b6b4b34e6a83f08aaa9d34b30023b9ccaf96ddbe20404eba" +checksum = "a43cade35f73ad81ba974fe1d5e1513331f87052af8377b26b00a838f39c6920" dependencies = [ "anyhow", "bytemuck", @@ -2329,9 +2540,9 @@ dependencies = [ [[package]] name = "risc0-circuit-rv32im" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb1caa759ab74d08779e062fcf98f5bd34397dfde572516a52369f0ec46db650" +checksum = "31440989146b342a7d37c15079c9568c69b7f988f3b789f422c7d4ed76526ddb" dependencies = [ "anyhow", "risc0-core", @@ -2342,19 +2553,37 @@ dependencies = [ [[package]] name = "risc0-core" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be79c89bcd18886b376073e3da22f8b7963247a42dce7b49cf3d09853f51641e" +checksum = "02e0cbd09d03c23b572b66cd96a56143adb22bf895aca89c1a153ccebedaa0b4" dependencies = [ "bytemuck", "rand_core", ] +[[package]] +name = "risc0-groth16" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1e9b8dae3f9c3862b6278b2812989a2f5a537975e5bd6a687f07cf1df68a36" +dependencies = [ + "anyhow", + "ark-bn254", + "ark-groth16", + "ark-serialize 0.4.2", + "hex", + "num-bigint", + "num-derive", + "num-traits", + "risc0-zkp", + "serde", +] + [[package]] name = "risc0-zkp" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e20a57e04840a5afadebb5d232546245f4fd8bd0e774bd69bf4bf25f8ab90c04" +checksum = "b96b035f744ecaaa7e9809c699bc85cf669cbab6f297f141d918e9b4c8098b79" dependencies = [ "anyhow", "blake2", @@ -2372,25 +2601,22 @@ dependencies = [ [[package]] name = "risc0-zkvm" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922588cb4b884b3951316a65581ccdfd1174af93c54093190878366812073329" +checksum = "2a1275834c86176efc122a172c2b5f271a8a5d792de7efbc47dfbecaaaff9432" dependencies = [ "anyhow", - "ark-bn254", - "ark-groth16", - "ark-serialize 0.4.2", "bytemuck", "cfg-if", "getrandom", "hex", - "num-bigint", "num-derive", "num-traits", "risc0-binfmt", "risc0-circuit-recursion", "risc0-circuit-rv32im", "risc0-core", + "risc0-groth16", "risc0-zkp", "risc0-zkvm-platform", "rrs-lib", @@ -2402,9 +2628,9 @@ dependencies = [ [[package]] name = "risc0-zkvm-platform" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5819c0c3bfd8f20b1226c9d4ca1f342eb3d8385e71211a9383a879643d1dde" +checksum = "03b6378c9e407be18a1560ed030fd87fb6056293c56263efac46c507ae97e0d7" dependencies = [ "bytemuck", "getrandom", @@ -2515,7 +2741,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -2637,6 +2863,7 @@ version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ + "rand", "secp256k1-sys", ] @@ -2711,7 +2938,7 @@ version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap", + "indexmap 2.2.3", "itoa", "ryu", "serde", @@ -2729,6 +2956,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +dependencies = [ + "base64 0.21.7", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.3", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2742,8 +2999,8 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" -source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2/v0.10.6-risc0#e75cafd9f55da196061f6fadf8bc8a86778192b7" +version = "0.10.8" +source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2-v0.10.8-risczero.0#244dc3b08788f7a4ccce14c66896ae3b4f24c166" dependencies = [ "cfg-if", "cpufeatures", @@ -2854,6 +3111,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.25.0" @@ -2919,9 +3182,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" +checksum = "cb3d0961cd53c23ea94eeec56ba940f636f6394788976e9f16ca5ee0aca7464a" dependencies = [ "paste", "proc-macro2", @@ -3139,7 +3402,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3150,7 +3413,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3161,7 +3424,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3476,6 +3739,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3717,6 +3989,7 @@ dependencies = [ "ruint", "serde", "serde_json", + "serde_with", "thiserror", "tokio", "zeth-primitives", @@ -3726,17 +3999,19 @@ dependencies = [ name = "zeth-primitives" version = "0.1.0" dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rlp-derive", "anyhow", "bytes", "ethers-core", - "k256", "log", - "revm-primitives", "rlp", "serde", + "serde_with", "sha2", "sha3", "thiserror", diff --git a/guests/op-compose/Cargo.toml b/guests/op-compose/Cargo.toml index d5ba155f..0b82c29c 100644 --- a/guests/op-compose/Cargo.toml +++ b/guests/op-compose/Cargo.toml @@ -6,14 +6,14 @@ edition = "2021" [workspace] [dependencies] -risc0-zkvm = { version = "0.20.1", default-features = false, features = ['std'] } +risc0-zkvm = { version = "0.21.0", default-features = false, features = ['std'] } zeth-lib = { path = "../../lib", default-features = false } [patch.crates-io] # use optimized risc0 circuit -crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.2-risc0" } +crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.3-risczero.0" } -sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2/v0.10.6-risc0" } +sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } [profile.release] codegen-units = 1 diff --git a/guests/op-derive/Cargo.lock b/guests/op-derive/Cargo.lock index dac01685..1b300269 100644 --- a/guests/op-derive/Cargo.lock +++ b/guests/op-derive/Cargo.lock @@ -50,11 +50,59 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "async-trait", + "futures-utils-wasm", + "serde", + "thiserror", +] + [[package]] name = "alloy-primitives" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" +checksum = "600d34d8de81e23b6d909c094e23b3d357e01ca36b78a8c5424c501eedbe86f0" dependencies = [ "alloy-rlp", "bytes", @@ -78,6 +126,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", ] @@ -93,16 +142,53 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + [[package]] name = "alloy-sol-macro" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" +checksum = "e86ec0a47740b20bc5613b8712d0d321d031c4efc58e9645af96085d5cccfc27" dependencies = [ "const-hex", "dunce", "heck", - "indexmap", + "indexmap 2.2.3", "proc-macro-error", "proc-macro2", "quote", @@ -113,9 +199,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" +checksum = "ad09ec5853fa700d12d778ad224dcdec636af424d29fad84fb9a2f16a5b0ef09" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -123,6 +209,21 @@ dependencies = [ "serde", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.79" @@ -170,7 +271,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", - "itertools", + "itertools 0.10.5", "num-traits", "zeroize", ] @@ -205,7 +306,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "digest 0.10.7", - "itertools", + "itertools 0.10.5", "num-bigint", "num-traits", "paste", @@ -403,9 +504,9 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", @@ -480,9 +581,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -579,9 +680,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d8c306be83ec04bf5f73710badd8edf56dea23f2f0d8b7f9fe4644d371c758" +checksum = "3130f3d8717cc02e668a896af24984d5d5d4e8bf12e278e982e0f1bd88a0f9af" dependencies = [ "blst", "cc", @@ -609,7 +710,11 @@ version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ + "android-tzdata", + "iana-time-zone", "num-traits", + "serde", + "windows-targets 0.52.0", ] [[package]] @@ -688,8 +793,8 @@ checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" -version = "0.5.2" -source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.2-risczero.0#8b30304277cfe553b51a78a0e693f48bbb059eb3" +version = "0.5.5" +source = "git+https://github.com/risc0/RustCrypto-crypto-bigint?tag=v0.5.5-risczero.0#3ab63a6f1048833f7047d5a50532e4a4cc789384" dependencies = [ "generic-array", "getrandom", @@ -708,6 +813,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.48", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.48", +] + [[package]] name = "dary_heap" version = "0.3.6" @@ -737,6 +877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -796,6 +937,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.16.9" @@ -1177,6 +1324,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxhash" version = "0.2.1" @@ -1255,13 +1408,19 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 2.2.3", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.13.2" @@ -1399,6 +1558,35 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -1447,6 +1635,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.2.3" @@ -1455,6 +1654,7 @@ checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] @@ -1481,6 +1681,15 @@ 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 = "itoa" version = "1.0.10" @@ -2041,7 +2250,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.2", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", @@ -2194,12 +2403,13 @@ dependencies = [ [[package]] name = "revm" -version = "5.0.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f86bdefa6dac07d92e2f5c37d7d183f2575b2f9e0ee9cba9402dfde912524" +checksum = "24fd3ed4b62dc61c647552d8b781811ae25ec74d23309055077e4dfb392444d2" dependencies = [ "auto_impl", "cfg-if", + "dyn-clone", "revm-interpreter", "revm-precompile", "serde", @@ -2208,9 +2418,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "2.1.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a80b516cc706630e604e2fd47c281501d2fb222712be4328921361388b7d2df" +checksum = "9f0a1818f8c876b0d71a0714217c34da7df8a42c0462750768779d55680e4554" dependencies = [ "revm-primitives", "serde", @@ -2218,9 +2428,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "4.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6912fafe7f70a264ec5895875ce2f2d0621a39263844280c9ee7f85e35bbb9e" +checksum = "7a9645a70f1df1e5bd7fa8718b9ba486fac9c3f0467aa6b58e7f590d5f6fd0f7" dependencies = [ "aurora-engine-modexp", "c-kzg", @@ -2235,16 +2445,17 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b3683a40f1e94e7389c8e81e5f26bb5d30875ed0b48ab07985ec32eb6d6c712" +checksum = "323ad597cf75ac9cb1d161be29fcc3562426f0278a1d04741697fca556e1ceea" dependencies = [ "alloy-primitives", "auto_impl", - "bitflags 2.4.2", + "bitflags 2.5.0", "bitvec", "c-kzg", "cfg-if", + "dyn-clone", "enumn", "hashbrown 0.14.3", "hex", @@ -2301,9 +2512,9 @@ dependencies = [ [[package]] name = "risc0-binfmt" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d263c6370d7714d2a634b6d88deb3871d0fad1f9486a9da6d48139c1ac85b26" +checksum = "2ae2939426c60756f910352184716a3538748208c9e11ade4a507db3b2757157" dependencies = [ "anyhow", "elf", @@ -2315,9 +2526,9 @@ dependencies = [ [[package]] name = "risc0-circuit-recursion" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9835069929a0e7b6b4b34e6a83f08aaa9d34b30023b9ccaf96ddbe20404eba" +checksum = "a43cade35f73ad81ba974fe1d5e1513331f87052af8377b26b00a838f39c6920" dependencies = [ "anyhow", "bytemuck", @@ -2329,9 +2540,9 @@ dependencies = [ [[package]] name = "risc0-circuit-rv32im" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb1caa759ab74d08779e062fcf98f5bd34397dfde572516a52369f0ec46db650" +checksum = "31440989146b342a7d37c15079c9568c69b7f988f3b789f422c7d4ed76526ddb" dependencies = [ "anyhow", "risc0-core", @@ -2342,19 +2553,37 @@ dependencies = [ [[package]] name = "risc0-core" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be79c89bcd18886b376073e3da22f8b7963247a42dce7b49cf3d09853f51641e" +checksum = "02e0cbd09d03c23b572b66cd96a56143adb22bf895aca89c1a153ccebedaa0b4" dependencies = [ "bytemuck", "rand_core", ] +[[package]] +name = "risc0-groth16" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1e9b8dae3f9c3862b6278b2812989a2f5a537975e5bd6a687f07cf1df68a36" +dependencies = [ + "anyhow", + "ark-bn254", + "ark-groth16", + "ark-serialize 0.4.2", + "hex", + "num-bigint", + "num-derive", + "num-traits", + "risc0-zkp", + "serde", +] + [[package]] name = "risc0-zkp" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e20a57e04840a5afadebb5d232546245f4fd8bd0e774bd69bf4bf25f8ab90c04" +checksum = "b96b035f744ecaaa7e9809c699bc85cf669cbab6f297f141d918e9b4c8098b79" dependencies = [ "anyhow", "blake2", @@ -2372,25 +2601,22 @@ dependencies = [ [[package]] name = "risc0-zkvm" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922588cb4b884b3951316a65581ccdfd1174af93c54093190878366812073329" +checksum = "2a1275834c86176efc122a172c2b5f271a8a5d792de7efbc47dfbecaaaff9432" dependencies = [ "anyhow", - "ark-bn254", - "ark-groth16", - "ark-serialize 0.4.2", "bytemuck", "cfg-if", "getrandom", "hex", - "num-bigint", "num-derive", "num-traits", "risc0-binfmt", "risc0-circuit-recursion", "risc0-circuit-rv32im", "risc0-core", + "risc0-groth16", "risc0-zkp", "risc0-zkvm-platform", "rrs-lib", @@ -2402,9 +2628,9 @@ dependencies = [ [[package]] name = "risc0-zkvm-platform" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5819c0c3bfd8f20b1226c9d4ca1f342eb3d8385e71211a9383a879643d1dde" +checksum = "03b6378c9e407be18a1560ed030fd87fb6056293c56263efac46c507ae97e0d7" dependencies = [ "bytemuck", "getrandom", @@ -2515,7 +2741,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -2637,6 +2863,7 @@ version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ + "rand", "secp256k1-sys", ] @@ -2711,7 +2938,7 @@ version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap", + "indexmap 2.2.3", "itoa", "ryu", "serde", @@ -2729,6 +2956,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +dependencies = [ + "base64 0.21.7", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.3", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2742,8 +2999,8 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" -source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2-v0.10.6-risczero.0#7fd6900c4f637bd15ee2642dfa77110f8f1ad065" +version = "0.10.8" +source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2-v0.10.8-risczero.0#244dc3b08788f7a4ccce14c66896ae3b4f24c166" dependencies = [ "cfg-if", "cpufeatures", @@ -2854,6 +3111,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.25.0" @@ -2919,9 +3182,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" +checksum = "cb3d0961cd53c23ea94eeec56ba940f636f6394788976e9f16ca5ee0aca7464a" dependencies = [ "paste", "proc-macro2", @@ -3139,7 +3402,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3150,7 +3413,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3161,7 +3424,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3476,6 +3739,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3717,6 +3989,7 @@ dependencies = [ "ruint", "serde", "serde_json", + "serde_with", "thiserror", "tokio", "zeth-primitives", @@ -3726,17 +3999,19 @@ dependencies = [ name = "zeth-primitives" version = "0.1.0" dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rlp-derive", "anyhow", "bytes", "ethers-core", - "k256", "log", - "revm-primitives", "rlp", "serde", + "serde_with", "sha2", "sha3", "thiserror", diff --git a/guests/op-derive/Cargo.toml b/guests/op-derive/Cargo.toml index b9adaacc..0545e106 100644 --- a/guests/op-derive/Cargo.toml +++ b/guests/op-derive/Cargo.toml @@ -6,14 +6,14 @@ edition = "2021" [workspace] [dependencies] -risc0-zkvm = { version = "0.20.1", default-features = false, features = ['std'] } +risc0-zkvm = { version = "0.21.0", default-features = false, features = ['std'] } zeth-lib = { path = "../../lib", default-features = false } [patch.crates-io] # use optimized risc0 circuit -crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.2-risczero.0" } +crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" } k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.3-risczero.0" } -sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.6-risczero.0" } +sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" } [profile.release] codegen-units = 1 diff --git a/host/Cargo.toml b/host/Cargo.toml index 34a6c891..472f47e7 100644 --- a/host/Cargo.toml +++ b/host/Cargo.toml @@ -24,10 +24,8 @@ hex = "0.4.3" log = "0.4" risc0-zkvm = { workspace = true, features = ["prove"] } serde = "1.0" -tempfile = "3.6" tokio = { version = "1.23", features = ["full"] } tracing = { version = "0.1", features = ["log"] } -typetag = "0.2.15" zeth-guests = { path = "../guests" } zeth-lib = { path = "../lib" } zeth-primitives = { path = "../primitives" } diff --git a/host/src/operations/build.rs b/host/src/operations/build.rs index 4ce611b1..295c819f 100644 --- a/host/src/operations/build.rs +++ b/host/src/operations/build.rs @@ -12,13 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::fmt::Debug; - use anyhow::Context; -use ethers_core::types::Transaction as EthersTransaction; use log::{info, warn}; use risc0_zkvm::{compute_image_id, Receipt}; -use serde::{Deserialize, Serialize}; use zeth_lib::{ builder::BlockBuilderStrategy, consts::ChainSpec, @@ -38,11 +34,7 @@ pub async fn build_block( rpc_url: Option, chain_spec: &ChainSpec, guest_elf: &[u8], -) -> anyhow::Result> -where - N::TxEssence: 'static + Send + TryFrom + Serialize + Deserialize<'static>, - >::Error: Debug, -{ +) -> anyhow::Result> { let build_args = cli.build_args().clone(); if build_args.block_count > 1 { warn!("Building multiple blocks is not supported. Only the first block will be built."); @@ -66,7 +58,7 @@ where let preflight_data = preflight_result.context("preflight failed")?; // Create the guest input from [Init] - let input: BlockBuildInput = preflight_data + let input: BlockBuildInput = preflight_data .clone() .try_into() .context("invalid preflight data")?; diff --git a/host/src/operations/mod.rs b/host/src/operations/mod.rs index 0d4f9c3d..872e3a10 100644 --- a/host/src/operations/mod.rs +++ b/host/src/operations/mod.rs @@ -24,10 +24,9 @@ use risc0_zkvm::{ compute_image_id, serde::to_vec, sha::{Digest, Digestible}, - Assumption, ExecutorEnv, ExecutorImpl, FileSegmentRef, Receipt, Segment, SegmentRef, + Assumption, ExecutorEnv, ExecutorImpl, Receipt, Segment, SegmentRef, }; use serde::{de::DeserializeOwned, Deserialize, Serialize}; -use tempfile::tempdir; use zeth_primitives::keccak::keccak; use crate::{cli::Cli, load_receipt, save_receipt}; @@ -311,7 +310,6 @@ pub fn prove_locally( encoded_input.len(), encoded_input.len() * 4 / 1_000_000 ); - let segment_dir = tempdir().unwrap(); info!("Running the prover..."); let session = { @@ -332,11 +330,7 @@ pub fn prove_locally( let env = env_builder.build().unwrap(); let mut exec = ExecutorImpl::from_elf(env, elf).unwrap(); - - exec.run_with_callback(|segment| { - Ok(Box::new(FileSegmentRef::new(&segment, segment_dir.path())?)) - }) - .unwrap() + exec.run().unwrap() }; session.prove().unwrap() } @@ -345,7 +339,6 @@ const NULL_SEGMENT_REF: NullSegmentRef = NullSegmentRef {}; #[derive(Serialize, Deserialize)] struct NullSegmentRef {} -#[typetag::serde] impl SegmentRef for NullSegmentRef { fn resolve(&self) -> anyhow::Result { unimplemented!() diff --git a/host/src/operations/rollups.rs b/host/src/operations/rollups.rs index 4c9348a5..87971e57 100644 --- a/host/src/operations/rollups.rs +++ b/host/src/operations/rollups.rs @@ -32,9 +32,8 @@ use zeth_lib::{ output::BlockBuildOutput, }; use zeth_primitives::{ - block::Header, mmr::{MerkleMountainRange, MerkleProof}, - transactions::optimism::OptimismTxEssence, + Header, }; use crate::{ @@ -43,7 +42,6 @@ use crate::{ }; pub async fn derive_rollup_blocks(cli: &Cli) -> anyhow::Result> { - info!("Fetching data ..."); let build_args = cli.build_args(); let op_builder_provider_factory = ProviderFactory::new( build_args.cache.clone(), @@ -276,7 +274,7 @@ pub async fn compose_derived_rollup_blocks( let mut sibling_map = Default::default(); let mut eth_mountain_range: MerkleMountainRange = Default::default(); for block in &complete_eth_chain { - eth_mountain_range.append_leaf(block.hash().0, Some(&mut sibling_map)); + eth_mountain_range.append_leaf(block.hash_slow().into(), Some(&mut sibling_map)); } let eth_chain_root = eth_mountain_range .root(Some(&mut sibling_map)) @@ -471,7 +469,7 @@ pub async fn compose_derived_rollup_blocks( async fn build_op_blocks( cli: &Cli, - op_block_inputs: Vec>, + op_block_inputs: Vec, ) -> (Vec, Vec, Vec) { let mut assumptions: Vec = vec![]; let mut bonsai_uuids = vec![]; diff --git a/host/src/operations/snarks.rs b/host/src/operations/snarks.rs index ceeb3810..dfab967b 100644 --- a/host/src/operations/snarks.rs +++ b/host/src/operations/snarks.rs @@ -17,10 +17,13 @@ use std::{str::FromStr, sync::Arc}; use alloy_primitives::U256; use alloy_sol_types::{sol, SolValue}; use anyhow::anyhow; -use bonsai_sdk::alpha::responses::{Groth16Seal, SnarkReceipt}; +use bonsai_sdk::alpha::responses::SnarkReceipt; use ethers_contract::abigen; use ethers_providers::{Http, Provider, RetryClient}; -use risc0_zkvm::sha::{Digest, Digestible}; +use risc0_zkvm::{ + sha::{Digest, Digestible}, + Groth16Seal, +}; use crate::cli::Cli; diff --git a/host/tests/cmd.rs b/host/tests/cmd.rs index da5ba370..b7fe2e6f 100644 --- a/host/tests/cmd.rs +++ b/host/tests/cmd.rs @@ -59,36 +59,36 @@ fn build_optimism(#[files("testdata/optimism/*.json.gz")] path: PathBuf) { .stderr(predicate::str::contains(" WARN ").not()); } -#[rstest] -#[case(109279674, 6)] -fn build_optimism_derived(#[case] block_number: u64, #[case] block_count: u64) { - Command::cargo_bin("zeth") - .unwrap() - .env("RUST_LOG", "info") - .args([ - "build", - "--network=optimism-derived", - "--cache=testdata/derivation", - &format!("--block-number={}", block_number), - &format!("--block-count={}", block_count), - ]) - .assert() - .success() - .stderr(predicate::str::contains(" WARN ").not()); - - // test composition - Command::cargo_bin("zeth") - .unwrap() - .env("RUST_LOG", "info") - .args([ - "build", - "--network=optimism-derived", - "--cache=testdata/derivation", - &format!("--block-number={}", block_number), - &format!("--block-count={}", block_count), - "--composition=1", - ]) - .assert() - .success() - .stderr(predicate::str::contains(" WARN ").not()); -} +// #[rstest] +// #[case(109279674, 6)] +// fn build_optimism_derived(#[case] block_number: u64, #[case] block_count: u64) { +// Command::cargo_bin("zeth") +// .unwrap() +// .env("RUST_LOG", "info") +// .args([ +// "build", +// "--network=optimism-derived", +// "--cache=testdata/derivation", +// &format!("--block-number={}", block_number), +// &format!("--block-count={}", block_count), +// ]) +// .assert() +// .success() +// .stderr(predicate::str::contains(" WARN ").not()); +// +// test composition +// Command::cargo_bin("zeth") +// .unwrap() +// .env("RUST_LOG", "info") +// .args([ +// "build", +// "--network=optimism-derived", +// "--cache=testdata/derivation", +// &format!("--block-number={}", block_number), +// &format!("--block-count={}", block_count), +// "--composition=1", +// ]) +// .assert() +// .success() +// .stderr(predicate::str::contains(" WARN ").not()); +// } diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 18693ffd..c8386bca 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -14,11 +14,12 @@ hashbrown = { workspace = true } libflate = "2.0.0" once_cell = "1.18" revm = { workspace = true } -risc0-zkvm = { version = "0.20.1", default-features = false, features = ['std'] } +risc0-zkvm = { version = "0.21.0", default-features = false, features = ["std"] } ruint = { version = "1.10", default-features = false } serde = "1.0" +serde_with = "3.7" thiserror = "1.0" -zeth-primitives = { path = "../primitives", features = ["revm", "ethers"] } +zeth-primitives = { path = "../primitives", features = ["ethers"] } [target.'cfg(not(target_os = "zkvm"))'.dependencies] chrono = { version = "0.4", default-features = false } @@ -27,7 +28,7 @@ flate2 = "1.0.26" log = "0.4" serde_json = { version = "1.0", default-features = false, features = ["alloc"] } tokio = { version = "1.23", features = ["full"] } -zeth-primitives = { path = "../primitives", features = ["revm", "ethers"] } +zeth-primitives = { path = "../primitives", features = ["ethers"] } [dev-dependencies] bincode = "1.3" diff --git a/lib/src/builder/execute/ethereum.rs b/lib/src/builder/execute/ethereum.rs index cf03e8a7..e0355f31 100644 --- a/lib/src/builder/execute/ethereum.rs +++ b/lib/src/builder/execute/ethereum.rs @@ -14,35 +14,36 @@ use core::{fmt::Debug, mem::take}; -use anyhow::{anyhow, bail, Context}; +use anyhow::{anyhow, bail, ensure, Context}; #[cfg(not(target_os = "zkvm"))] use log::{debug, trace}; use revm::{ interpreter::Host, - primitives::{Account, Address, ResultAndState, SpecId, TransactTo, TxEnv}, + primitives::{Account, ResultAndState, SpecId, TransactTo, TxEnv, MAX_BLOB_GAS_PER_BLOCK}, Database, DatabaseCommit, Evm, }; use ruint::aliases::U256; use zeth_primitives::{ alloy_rlp, - receipt::Receipt, - transactions::{ - ethereum::{EthereumTxEssence, TransactionKind}, - TxEssence, - }, + receipt::{EthReceiptEnvelope, Receipt, ReceiptEnvelope}, + transactions::{EthTxEnvelope, EvmTransaction, TxEnvelope, TxType}, trie::MptNode, - Bloom, + Address, Bloom, }; use super::TxExecStrategy; -use crate::{builder::BlockBuilder, consts, guest_mem_forget}; +use crate::{ + builder::BlockBuilder, + consts::{self, BEACON_ROOTS_ADDRESS, SYSTEM_ADDRESS}, + guest_mem_forget, +}; pub struct EthTxExecStrategy {} -impl TxExecStrategy for EthTxExecStrategy { +impl TxExecStrategy for EthTxExecStrategy { fn execute_transactions( - mut block_builder: BlockBuilder, - ) -> anyhow::Result> + mut block_builder: BlockBuilder, + ) -> anyhow::Result> where D: Database + DatabaseCommit, ::Error: Debug, @@ -63,7 +64,7 @@ impl TxExecStrategy for EthTxExecStrategy { .state_input .timestamp .try_into() - .unwrap(), + .unwrap_or(32503676400), 0, ) .unwrap(); @@ -84,7 +85,6 @@ impl TxExecStrategy for EthTxExecStrategy { block_builder.input.state_input.beneficiary ); trace!(" Gas limit: {}", block_builder.input.state_input.gas_limit); - trace!(" Base fee per gas: {}", header.base_fee_per_gas); trace!( " Extra data: {:?}", block_builder.input.state_input.extra_data @@ -99,11 +99,15 @@ impl TxExecStrategy for EthTxExecStrategy { // set the EVM block environment blk_env.number = header.number.try_into().unwrap(); blk_env.coinbase = block_builder.input.state_input.beneficiary; - blk_env.timestamp = header.timestamp; + blk_env.timestamp = U256::from(header.timestamp); + blk_env.gas_limit = U256::from(block_builder.input.state_input.gas_limit); + blk_env.basefee = U256::from(header.base_fee_per_gas.unwrap_or_default()); blk_env.difficulty = U256::ZERO; blk_env.prevrandao = Some(header.mix_hash); - blk_env.basefee = header.base_fee_per_gas; - blk_env.gas_limit = block_builder.input.state_input.gas_limit; + // EIP-4844 excess blob gas of this block, introduced in Cancun + if let Some(excess_blob_gas) = header.excess_blob_gas { + blk_env.set_blob_excess_gas_and_price(excess_blob_gas) + } }) .modify_cfg_env(|cfg_env| { // set the EVM configuration @@ -111,10 +115,44 @@ impl TxExecStrategy for EthTxExecStrategy { }) .build(); + // set the beacon block root in the EVM + if spec_id >= SpecId::CANCUN { + let parent_beacon_block_root = header.parent_beacon_block_root.unwrap(); + + // From EIP-4788 Beacon block root in the EVM (Cancun): + // "Call BEACON_ROOTS_ADDRESS as SYSTEM_ADDRESS with the 32-byte input of + // header.parent_beacon_block_root, a gas limit of 30_000_000, and 0 value." + evm.env_mut().tx = TxEnv { + transact_to: TransactTo::Call(BEACON_ROOTS_ADDRESS), + caller: SYSTEM_ADDRESS, + data: parent_beacon_block_root.0.into(), + gas_limit: 30_000_000, + value: U256::ZERO, + ..Default::default() + }; + + let tmp = evm.env_mut().block.clone(); + + // disable block gas limit validation and base fee checks + evm.block_mut().gas_limit = U256::from(evm.tx().gas_limit); + evm.block_mut().basefee = U256::ZERO; + + let ResultAndState { mut state, .. } = + evm.transact().expect("beacon roots contract call failed"); + evm.env_mut().block = tmp; + + // commit only the changes to the beacon roots contract + state.remove(&SYSTEM_ADDRESS); + state.remove(&evm.block().coinbase); + evm.context.evm.db.commit(state); + } + // bloom filter over all transaction logs let mut logs_bloom = Bloom::default(); // keep track of the gas used over all transactions - let mut cumulative_gas_used = consts::ZERO; + let mut cumulative_gas_used = 0_u64; + + let mut blob_gas_used = 0_u64; // process all the transactions let mut tx_trie = MptNode::default(); @@ -124,50 +162,74 @@ impl TxExecStrategy for EthTxExecStrategy { .enumerate() { // verify the transaction signature - let tx_from = tx - .recover_from() + let tx_from: Address = tx + .from() .with_context(|| format!("Error recovering address for transaction {}", tx_no))?; #[cfg(not(target_os = "zkvm"))] { let tx_hash = tx.hash(); trace!("Tx no. {} (hash: {})", tx_no, tx_hash); - trace!(" Type: {}", tx.essence.tx_type()); + trace!(" Type: {:?}", tx.tx_type()); trace!(" Fr: {:?}", tx_from); - trace!(" To: {:?}", tx.essence.to().unwrap_or_default()); + trace!(" To: {:?}", tx.to().to().unwrap_or_default()); } - // verify transaction gas + // validate transaction gas let block_available_gas = block_builder.input.state_input.gas_limit - cumulative_gas_used; - if block_available_gas < tx.essence.gas_limit() { + if block_available_gas < tx.gas_limit() { bail!("Error at transaction {}: gas exceeds block limit", tx_no); } + // validity blob gas + if let TxEnvelope::Ethereum(EthTxEnvelope::Eip4844(blob_tx)) = &tx { + let tx = blob_tx.tx().tx(); + blob_gas_used = blob_gas_used.checked_add(tx.blob_gas()).unwrap(); + ensure!( + blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK, + "Error at transaction {}: total blob gas spent exceeds the limit", + tx_no + ); + } + + let TxEnvelope::Ethereum(essence) = &tx else { + unreachable!("OptimismDeposit transactions are not supported") + }; + // process the transaction - fill_eth_tx_env(&mut evm.env_mut().tx, &tx.essence, tx_from); + fill_eth_tx_env(&mut evm.env_mut().tx, essence, tx_from); let ResultAndState { result, state } = evm .transact() .map_err(|evm_err| anyhow!("Error at transaction {}: {:?}", tx_no, evm_err)) // todo: change unrecoverable panic to host-side recoverable `Result` - .expect("Block construction failure."); + .expect("Block construction failure"); - let gas_used = result.gas_used().try_into().unwrap(); + let gas_used = result.gas_used(); cumulative_gas_used = cumulative_gas_used.checked_add(gas_used).unwrap(); #[cfg(not(target_os = "zkvm"))] trace!(" Ok: {:?}", result); // create the receipt from the EVM result - let receipt = Receipt::new( - tx.essence.tx_type(), - result.is_success(), + let receipt = Receipt { + success: result.is_success(), cumulative_gas_used, - result.logs().into_iter().map(|log| log.into()).collect(), - ); + logs: result.into_logs(), + } + .with_bloom(); // accumulate logs to the block bloom filter - logs_bloom.accrue_bloom(&receipt.payload.logs_bloom); + logs_bloom.accrue_bloom(&receipt.bloom); + + // create the EIP-2718 enveloped receipt + let receipt = match tx.tx_type() { + TxType::Legacy => ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Legacy(receipt)), + TxType::Eip2930 => ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Eip2930(receipt)), + TxType::Eip1559 => ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Eip1559(receipt)), + TxType::Eip4844 => ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Eip4844(receipt)), + TxType::OptimismDeposit => unreachable!(), + }; // Add receipt and tx to tries let trie_key = alloy_rlp::encode(tx_no); @@ -247,68 +309,101 @@ impl TxExecStrategy for EthTxExecStrategy { header.receipts_root = receipt_trie.hash(); header.logs_bloom = logs_bloom; header.gas_used = cumulative_gas_used; - header.withdrawals_root = if spec_id < SpecId::SHANGHAI { - None - } else { - Some(withdrawals_trie.hash()) - }; + if spec_id >= SpecId::SHANGHAI { + header.withdrawals_root = Some(withdrawals_trie.hash()); + } + if spec_id >= SpecId::CANCUN { + header.blob_gas_used = Some(blob_gas_used); + } // Leak memory, save cycles guest_mem_forget([tx_trie, receipt_trie, withdrawals_trie]); // Return block builder with updated database - Ok(block_builder.with_db(evm.context.evm.db)) + Ok(block_builder.with_db(evm.context.evm.inner.db)) } } -pub fn fill_eth_tx_env(tx_env: &mut TxEnv, essence: &EthereumTxEssence, caller: Address) { +pub fn fill_eth_tx_env(tx_env: &mut TxEnv, essence: &EthTxEnvelope, caller: Address) { match essence { - EthereumTxEssence::Legacy(tx) => { + EthTxEnvelope::Legacy(tx) => { + let tx = tx.tx(); + tx_env.caller = caller; - tx_env.gas_limit = tx.gas_limit.try_into().unwrap(); - tx_env.gas_price = tx.gas_price; + tx_env.gas_limit = tx.gas_limit; + tx_env.gas_price = U256::from(tx.gas_price); tx_env.gas_priority_fee = None; - tx_env.transact_to = if let TransactionKind::Call(to_addr) = tx.to { + tx_env.transact_to = if let Some(to_addr) = tx.to.to() { TransactTo::Call(to_addr) } else { TransactTo::create() }; tx_env.value = tx.value; - tx_env.data = tx.data.clone(); + tx_env.data = tx.input.clone(); tx_env.chain_id = tx.chain_id; tx_env.nonce = Some(tx.nonce); tx_env.access_list.clear(); + tx_env.blob_hashes.clear(); + tx_env.max_fee_per_blob_gas.take(); } - EthereumTxEssence::Eip2930(tx) => { + EthTxEnvelope::Eip2930(tx) => { + let tx = tx.tx(); + tx_env.caller = caller; - tx_env.gas_limit = tx.gas_limit.try_into().unwrap(); - tx_env.gas_price = tx.gas_price; + tx_env.gas_limit = tx.gas_limit; + tx_env.gas_price = U256::from(tx.gas_price); tx_env.gas_priority_fee = None; - tx_env.transact_to = if let TransactionKind::Call(to_addr) = tx.to { + tx_env.transact_to = if let Some(to_addr) = tx.to.to() { TransactTo::Call(to_addr) } else { TransactTo::create() }; tx_env.value = tx.value; - tx_env.data = tx.data.clone(); + tx_env.data = tx.input.clone(); tx_env.chain_id = Some(tx.chain_id); tx_env.nonce = Some(tx.nonce); - tx_env.access_list = tx.access_list.clone().into(); + tx_env.access_list = tx.access_list.flattened(); + tx_env.blob_hashes.clear(); + tx_env.max_fee_per_blob_gas.take(); } - EthereumTxEssence::Eip1559(tx) => { + EthTxEnvelope::Eip1559(tx) => { + let tx = tx.tx(); + + tx_env.caller = caller; + tx_env.gas_limit = tx.gas_limit; + tx_env.gas_price = U256::from(tx.max_fee_per_gas); + tx_env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas)); + tx_env.transact_to = if let Some(to_addr) = tx.to.to() { + TransactTo::Call(to_addr) + } else { + TransactTo::create() + }; + tx_env.value = tx.value; + tx_env.data = tx.input.clone(); + tx_env.chain_id = Some(tx.chain_id); + tx_env.nonce = Some(tx.nonce); + tx_env.access_list = tx.access_list.flattened(); + tx_env.blob_hashes.clear(); + tx_env.max_fee_per_blob_gas.take(); + } + EthTxEnvelope::Eip4844(tx) => { + let tx = tx.tx().tx(); + tx_env.caller = caller; - tx_env.gas_limit = tx.gas_limit.try_into().unwrap(); - tx_env.gas_price = tx.max_fee_per_gas; - tx_env.gas_priority_fee = Some(tx.max_priority_fee_per_gas); - tx_env.transact_to = if let TransactionKind::Call(to_addr) = tx.to { + tx_env.gas_limit = tx.gas_limit; + tx_env.gas_price = U256::from(tx.max_fee_per_gas); + tx_env.gas_priority_fee = Some(U256::from(tx.max_priority_fee_per_gas)); + tx_env.transact_to = if let Some(to_addr) = tx.to.to() { TransactTo::Call(to_addr) } else { TransactTo::create() }; tx_env.value = tx.value; - tx_env.data = tx.data.clone(); + tx_env.data = tx.input.clone(); tx_env.chain_id = Some(tx.chain_id); tx_env.nonce = Some(tx.nonce); - tx_env.access_list = tx.access_list.clone().into(); + tx_env.access_list = tx.access_list.flattened(); + tx_env.blob_hashes = tx.blob_versioned_hashes.clone(); + tx_env.max_fee_per_blob_gas = Some(U256::from(tx.max_fee_per_blob_gas)); } }; } diff --git a/lib/src/builder/execute/mod.rs b/lib/src/builder/execute/mod.rs index e0cf8bab..6f77effa 100644 --- a/lib/src/builder/execute/mod.rs +++ b/lib/src/builder/execute/mod.rs @@ -16,15 +16,14 @@ use core::fmt::Debug; use anyhow::Result; use revm::{Database, DatabaseCommit}; -use zeth_primitives::transactions::TxEssence; use super::BlockBuilder; pub(super) mod ethereum; pub(super) mod optimism; -pub trait TxExecStrategy { - fn execute_transactions(block_builder: BlockBuilder) -> Result> +pub trait TxExecStrategy { + fn execute_transactions(block_builder: BlockBuilder) -> Result> where D: Database + DatabaseCommit, ::Error: Debug; diff --git a/lib/src/builder/execute/optimism.rs b/lib/src/builder/execute/optimism.rs index b72b39a1..4f9b3bc7 100644 --- a/lib/src/builder/execute/optimism.rs +++ b/lib/src/builder/execute/optimism.rs @@ -16,7 +16,7 @@ use core::{fmt::Debug, mem::take}; use anyhow::{anyhow, bail, Context, Result}; #[cfg(not(target_os = "zkvm"))] -use log::trace; +use log::{debug, trace}; use revm::{ interpreter::Host, primitives::{Address, ResultAndState, SpecId, TransactTo, TxEnv}, @@ -25,25 +25,21 @@ use revm::{ use ruint::aliases::U256; use zeth_primitives::{ alloy_rlp, - receipt::Receipt, + receipt::{EthReceiptEnvelope, OptimismDepositReceipt, Receipt, ReceiptEnvelope}, transactions::{ - ethereum::{EthereumTxEssence, TransactionKind}, - optimism::{OptimismTxEssence, TxEssenceOptimismDeposited}, - TxEssence, + optimism::TxOptimismDeposit, EthTxEnvelope, EvmTransaction as _, TxEnvelope, TxType, }, trie::{MptNode, EMPTY_ROOT}, Bloom, Bytes, }; use super::{ethereum, TxExecStrategy}; -use crate::{builder::BlockBuilder, consts, guest_mem_forget}; +use crate::{builder::BlockBuilder, guest_mem_forget}; pub struct OpTxExecStrategy {} -impl TxExecStrategy for OpTxExecStrategy { - fn execute_transactions( - mut block_builder: BlockBuilder, - ) -> Result> +impl TxExecStrategy for OpTxExecStrategy { + fn execute_transactions(mut block_builder: BlockBuilder) -> Result> where D: Database + DatabaseCommit, ::Error: Debug, @@ -69,9 +65,9 @@ impl TxExecStrategy for OpTxExecStrategy { ) .unwrap(); - trace!("Block no. {}", header.number); - trace!(" EVM spec ID: {:?}", spec_id); - trace!(" Timestamp: {}", dt); + debug!("Block no. {}", header.number); + debug!(" EVM spec ID: {:?}", spec_id); + debug!(" Timestamp: {}", dt); trace!( " Transactions: {}", block_builder.input.state_input.transactions.len() @@ -81,7 +77,6 @@ impl TxExecStrategy for OpTxExecStrategy { block_builder.input.state_input.beneficiary ); trace!(" Gas limit: {}", block_builder.input.state_input.gas_limit); - trace!(" Base fee per gas: {}", header.base_fee_per_gas); trace!( " Extra data: {:?}", block_builder.input.state_input.extra_data @@ -97,11 +92,11 @@ impl TxExecStrategy for OpTxExecStrategy { // set the EVM block environment blk_env.number = header.number.try_into().unwrap(); blk_env.coinbase = block_builder.input.state_input.beneficiary; - blk_env.timestamp = header.timestamp; + blk_env.timestamp = U256::from(header.timestamp); blk_env.difficulty = U256::ZERO; blk_env.prevrandao = Some(header.mix_hash); - blk_env.basefee = header.base_fee_per_gas; - blk_env.gas_limit = block_builder.input.state_input.gas_limit; + blk_env.basefee = U256::from(header.base_fee_per_gas.unwrap_or_default()); + blk_env.gas_limit = U256::from(block_builder.input.state_input.gas_limit); }) .modify_cfg_env(|cfg_env| { // set the EVM configuration @@ -112,7 +107,7 @@ impl TxExecStrategy for OpTxExecStrategy { // bloom filter over all transaction logs let mut logs_bloom = Bloom::default(); // keep track of the gas used over all transactions - let mut cumulative_gas_used = consts::ZERO; + let mut cumulative_gas_used = 0_u64; // process all the transactions let mut tx_trie = MptNode::default(); @@ -123,53 +118,48 @@ impl TxExecStrategy for OpTxExecStrategy { { // verify the transaction signature let tx_from = tx - .recover_from() + .from() .with_context(|| format!("Error recovering address for transaction {}", tx_no))?; #[cfg(not(target_os = "zkvm"))] { let tx_hash = tx.hash(); trace!("Tx no. {} (hash: {})", tx_no, tx_hash); - trace!(" Type: {}", tx.essence.tx_type()); + trace!(" Type: {:?}", tx.tx_type()); trace!(" Fr: {:?}", tx_from); - trace!(" To: {:?}", tx.essence.to().unwrap_or_default()); + trace!(" To: {:?}", tx.to().to().unwrap_or_default()); } // verify transaction gas let block_available_gas = block_builder.input.state_input.gas_limit - cumulative_gas_used; - if block_available_gas < tx.essence.gas_limit() { + if block_available_gas < tx.gas_limit() { bail!("Error at transaction {}: gas exceeds block limit", tx_no); } // cache account nonce if the transaction is a deposit, starting with Canyon let deposit_nonce = (spec_id >= SpecId::CANYON - && matches!(tx.essence, OptimismTxEssence::OptimismDeposited(_))) + && matches!(tx, TxEnvelope::OptimismDeposit(_))) .then(|| { let db = &mut evm.context.evm.db; let account = db.basic(tx_from).expect("Depositor account not found"); account.unwrap_or_default().nonce }); - match &tx.essence { - OptimismTxEssence::OptimismDeposited(deposit) => { + match &tx { + TxEnvelope::OptimismDeposit(op) => { #[cfg(not(target_os = "zkvm"))] { - trace!(" Source: {:?}", &deposit.source_hash); - trace!(" Mint: {:?}", &deposit.mint); - trace!(" System Tx: {:?}", deposit.is_system_tx); + trace!(" Source: {:?}", &op.source_hash); + trace!(" Mint: {:?}", &op.mint); + trace!(" System Tx: {:?}", op.is_system_tx); } // Initialize tx environment - fill_deposit_tx_env(&mut evm.env_mut().tx, deposit, tx_from); + fill_deposit_tx_env(&mut evm.env_mut().tx, op, tx_from); } - OptimismTxEssence::Ethereum(essence) => { - fill_eth_tx_env( - &mut evm.env_mut().tx, - alloy_rlp::encode(&tx), - essence, - tx_from, - ); + TxEnvelope::Ethereum(eth) => { + fill_eth_tx_env(&mut evm.env_mut().tx, alloy_rlp::encode(&tx), eth, tx_from); } }; @@ -178,24 +168,45 @@ impl TxExecStrategy for OpTxExecStrategy { .transact() .map_err(|evm_err| anyhow!("Error at transaction {}: {:?}", tx_no, evm_err)) // todo: change unrecoverable panic to host-side recoverable `Result` - .expect("Block construction failure."); + .expect("Block construction failure"); - let gas_used = result.gas_used().try_into().unwrap(); - cumulative_gas_used = cumulative_gas_used.checked_add(gas_used).unwrap(); + cumulative_gas_used = cumulative_gas_used.checked_add(result.gas_used()).unwrap(); #[cfg(not(target_os = "zkvm"))] trace!(" Ok: {:?}", result); // create the receipt from the EVM result - let mut receipt = Receipt::new( - tx.essence.tx_type(), - result.is_success(), + let receipt = Receipt { + success: result.is_success(), cumulative_gas_used, - result.logs().into_iter().map(|log| log.into()).collect(), - ); - if let Some(nonce) = deposit_nonce { - receipt = receipt.with_deposit_nonce(nonce); + logs: result.into_logs(), } + .with_bloom(); + + // accumulate logs to the block bloom filter + logs_bloom.accrue_bloom(&receipt.bloom); + + // create the EIP-2718 enveloped receipt + let receipt = match tx.tx_type() { + TxType::Legacy => ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Legacy(receipt)), + TxType::Eip2930 => ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Eip2930(receipt)), + TxType::Eip1559 => ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Eip1559(receipt)), + TxType::Eip4844 => ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Eip4844(receipt)), + TxType::OptimismDeposit => ReceiptEnvelope::OptimismDeposit( + OptimismDepositReceipt::new(receipt, deposit_nonce), + ), + }; + + // Add receipt and tx to tries + let trie_key = alloy_rlp::encode(tx_no); + tx_trie + .insert_rlp(&trie_key, tx) + // todo: change unrecoverable panic to host-side recoverable `Result` + .expect("failed to insert transaction"); + receipt_trie + .insert_rlp(&trie_key, receipt) + // todo: change unrecoverable panic to host-side recoverable `Result` + .expect("failed to insert receipt"); // update account states #[cfg(not(target_os = "zkvm"))] @@ -203,11 +214,12 @@ impl TxExecStrategy for OpTxExecStrategy { if account.is_touched() { // log account trace!( - " State {:?} (is_selfdestructed={}, is_loaded_as_not_existing={}, is_created={})", + " State {:?} (is_selfdestructed={}, is_loaded_as_not_existing={}, is_created={}, is_empty={})", address, account.is_selfdestructed(), account.is_loaded_as_not_existing(), - account.is_created() + account.is_created(), + account.is_empty(), ); // log balance changes trace!( @@ -228,20 +240,6 @@ impl TxExecStrategy for OpTxExecStrategy { } evm.context.evm.db.commit(state); - - // accumulate logs to the block bloom filter - logs_bloom.accrue_bloom(&receipt.payload.logs_bloom); - - // Add receipt and tx to tries - let trie_key = alloy_rlp::encode(tx_no); - tx_trie - .insert_rlp(&trie_key, tx) - // todo: change unrecoverable panic to host-side recoverable `Result` - .expect("failed to insert transaction"); - receipt_trie - .insert_rlp(&trie_key, receipt) - // todo: change unrecoverable panic to host-side recoverable `Result` - .expect("failed to insert receipt"); } // Update result header with computed values @@ -258,34 +256,34 @@ impl TxExecStrategy for OpTxExecStrategy { // Leak memory, save cycles guest_mem_forget([tx_trie, receipt_trie]); // Return block builder with updated database - Ok(block_builder.with_db(evm.context.evm.db)) + Ok(block_builder.with_db(evm.context.evm.inner.db)) } } -fn fill_deposit_tx_env(tx_env: &mut TxEnv, essence: &TxEssenceOptimismDeposited, caller: Address) { +fn fill_deposit_tx_env(tx_env: &mut TxEnv, tx: &TxOptimismDeposit, caller: Address) { // initialize additional optimism tx fields - tx_env.optimism.source_hash = Some(essence.source_hash); - tx_env.optimism.mint = Some(essence.mint.try_into().unwrap()); - tx_env.optimism.is_system_transaction = Some(essence.is_system_tx); + tx_env.optimism.source_hash = Some(tx.source_hash); + tx_env.optimism.mint = Some(tx.mint.try_into().unwrap()); + tx_env.optimism.is_system_transaction = Some(tx.is_system_tx); tx_env.optimism.enveloped_tx = None; // only used for non-deposit txs tx_env.caller = caller; // previously overridden to tx.from - tx_env.gas_limit = essence.gas_limit.try_into().unwrap(); + tx_env.gas_limit = tx.gas_limit; tx_env.gas_price = U256::ZERO; tx_env.gas_priority_fee = None; - tx_env.transact_to = if let TransactionKind::Call(to_addr) = essence.to { + tx_env.transact_to = if let Some(to_addr) = tx.to.to() { TransactTo::Call(to_addr) } else { TransactTo::create() }; - tx_env.value = essence.value; - tx_env.data = essence.data.clone(); + tx_env.value = tx.value; + tx_env.data = tx.input.clone(); tx_env.chain_id = None; tx_env.nonce = None; tx_env.access_list.clear(); } -fn fill_eth_tx_env(tx_env: &mut TxEnv, tx: Vec, essence: &EthereumTxEssence, caller: Address) { +fn fill_eth_tx_env(tx_env: &mut TxEnv, tx: Vec, essence: &EthTxEnvelope, caller: Address) { // initialize additional optimism tx fields tx_env.optimism.source_hash = None; tx_env.optimism.mint = None; diff --git a/lib/src/builder/finalize.rs b/lib/src/builder/finalize.rs index f825cf28..e7466be0 100644 --- a/lib/src/builder/finalize.rs +++ b/lib/src/builder/finalize.rs @@ -17,11 +17,9 @@ use core::mem; use anyhow::Result; use revm::{Database, DatabaseCommit}; use zeth_primitives::{ - block::Header, keccak::keccak, - transactions::TxEssence, trie::{MptNode, StateAccount}, - U256, + Header, U256, }; use crate::{ @@ -35,17 +33,13 @@ where D: Database + DatabaseCommit, ::Error: core::fmt::Debug, { - fn finalize(block_builder: BlockBuilder) -> Result<(Header, MptNode)> - where - E: TxEssence; + fn finalize(block_builder: BlockBuilder) -> Result<(Header, MptNode)>; } pub struct MemDbBlockFinalizeStrategy {} impl BlockFinalizeStrategy for MemDbBlockFinalizeStrategy { - fn finalize( - mut block_builder: BlockBuilder, - ) -> Result<(Header, MptNode)> { + fn finalize(mut block_builder: BlockBuilder) -> Result<(Header, MptNode)> { let db = block_builder.db.take().expect("DB not initialized"); // apply state updates diff --git a/lib/src/builder/initialize.rs b/lib/src/builder/initialize.rs index e291e332..811ce539 100644 --- a/lib/src/builder/initialize.rs +++ b/lib/src/builder/initialize.rs @@ -15,14 +15,12 @@ use core::mem; use anyhow::{bail, Result}; -use hashbrown::HashMap; use revm::{ - primitives::{AccountInfo, Bytecode, B256}, + primitives::{AccountInfo, Bytecode, HashMap, B256}, Database, DatabaseCommit, }; use zeth_primitives::{ keccak::{keccak, KECCAK_EMPTY}, - transactions::TxEssence, trie::StateAccount, Bytes, }; @@ -39,17 +37,13 @@ where D: Database + DatabaseCommit, ::Error: core::fmt::Debug, { - fn initialize_database(block_builder: BlockBuilder) -> Result> - where - E: TxEssence; + fn initialize_database(block_builder: BlockBuilder) -> Result>; } pub struct MemDbInitStrategy {} impl DbInitStrategy for MemDbInitStrategy { - fn initialize_database( - mut block_builder: BlockBuilder, - ) -> Result> { + fn initialize_database(mut block_builder: BlockBuilder) -> Result> { // Verify state trie root if block_builder.input.parent_state_trie.hash() != block_builder.input.state_input.parent_header.state_root @@ -127,11 +121,11 @@ impl DbInitStrategy for MemDbInitStrategy { HashMap::with_capacity(block_builder.input.ancestor_headers.len() + 1); block_hashes.insert( block_builder.input.state_input.parent_header.number, - block_builder.input.state_input.parent_header.hash(), + block_builder.input.state_input.parent_header.hash_slow(), ); let mut prev = &block_builder.input.state_input.parent_header; for current in &block_builder.input.ancestor_headers { - let current_hash = current.hash(); + let current_hash = current.hash_slow(); if prev.parent_hash != current_hash { bail!( "Invalid chain: {} is not the parent of {}", diff --git a/lib/src/builder/mod.rs b/lib/src/builder/mod.rs index ff64d866..3438dc78 100644 --- a/lib/src/builder/mod.rs +++ b/lib/src/builder/mod.rs @@ -17,12 +17,7 @@ use std::sync::{Arc, Mutex}; use anyhow::Result; use revm::{primitives::SpecId, Database, DatabaseCommit}; -use serde::Serialize; -use zeth_primitives::{ - block::Header, - transactions::{ethereum::EthereumTxEssence, optimism::OptimismTxEssence, TxEssence}, - trie::MptNode, -}; +use zeth_primitives::{trie::MptNode, Header}; use crate::{ builder::{ @@ -49,9 +44,9 @@ type DatabaseRescue = core::marker::PhantomData; /// A generic builder for building a block. #[derive(Clone, Debug)] -pub struct BlockBuilder<'a, D, E: TxEssence> { +pub struct BlockBuilder<'a, D> { pub(crate) chain_spec: &'a ChainSpec, - pub(crate) input: BlockBuildInput, + pub(crate) input: BlockBuildInput, pub(crate) db: Option, pub(crate) spec_id: Option, pub(crate) header: Option
, @@ -60,7 +55,7 @@ pub struct BlockBuilder<'a, D, E: TxEssence> { // This implementation allows us to recover data during erroneous block builds on the host #[cfg(not(target_os = "zkvm"))] -impl<'a, D, E: TxEssence> Drop for BlockBuilder<'a, D, E> { +impl<'a, D> Drop for BlockBuilder<'a, D> { fn drop(&mut self) { if let Some(backup_target) = &mut self.db_drop_destination { if let Some(dropped_db) = self.db.take() { @@ -72,18 +67,17 @@ impl<'a, D, E: TxEssence> Drop for BlockBuilder<'a, D, E> { } } -impl BlockBuilder<'_, D, E> +impl BlockBuilder<'_, D> where D: Database + DatabaseCommit, ::Error: core::fmt::Debug, - E: TxEssence, { /// Creates a new block builder. pub fn new( chain_spec: &ChainSpec, - input: BlockBuildInput, + input: BlockBuildInput, db_backup: Option>, - ) -> BlockBuilder<'_, D, E> { + ) -> BlockBuilder<'_, D> { BlockBuilder { chain_spec, db: None, @@ -111,7 +105,7 @@ where } /// Executes all input transactions. - pub fn execute_transactions>(self) -> Result { + pub fn execute_transactions(self) -> Result { T::execute_transactions(self) } @@ -138,21 +132,16 @@ where /// A bundle of strategies for building a block using [BlockBuilder]. pub trait BlockBuilderStrategy { - type TxEssence: TxEssence + Serialize; - type DbInitStrategy: DbInitStrategy; type HeaderPrepStrategy: HeaderPrepStrategy; - type TxExecStrategy: TxExecStrategy; + type TxExecStrategy: TxExecStrategy; type BlockFinalizeStrategy: BlockFinalizeStrategy; /// Builds a block from the given input. - fn build_from( - chain_spec: &ChainSpec, - input: BlockBuildInput, - ) -> Result { + fn build_from(chain_spec: &ChainSpec, input: BlockBuildInput) -> Result { let input_hash = input.state_input.hash(); - let builder = BlockBuilder::::new(chain_spec, input, None); + let builder = BlockBuilder::::new(chain_spec, input, None); // Database initialization errors do not indicate a faulty block let initialized = builder.initialize_database::()?; @@ -181,7 +170,7 @@ pub trait BlockBuilderStrategy { let (header, state) = executed.finalize::()?; Ok(BlockBuildOutput::SUCCESS { - hash: header.hash(), + hash: header.hash_slow(), head: header, state, state_input_hash: input_hash.into(), @@ -193,7 +182,6 @@ pub trait BlockBuilderStrategy { pub struct EthereumStrategy {} impl BlockBuilderStrategy for EthereumStrategy { - type TxEssence = EthereumTxEssence; type DbInitStrategy = MemDbInitStrategy; type HeaderPrepStrategy = EthHeaderPrepStrategy; type TxExecStrategy = EthTxExecStrategy; @@ -204,7 +192,6 @@ impl BlockBuilderStrategy for EthereumStrategy { pub struct OptimismStrategy {} impl BlockBuilderStrategy for OptimismStrategy { - type TxEssence = OptimismTxEssence; type DbInitStrategy = MemDbInitStrategy; type HeaderPrepStrategy = EthHeaderPrepStrategy; type TxExecStrategy = OpTxExecStrategy; diff --git a/lib/src/builder/prepare.rs b/lib/src/builder/prepare.rs index e8a4450d..544d1850 100644 --- a/lib/src/builder/prepare.rs +++ b/lib/src/builder/prepare.rs @@ -15,66 +15,63 @@ use core::fmt::Debug; use anyhow::{bail, Context, Result}; -use revm::{Database, DatabaseCommit}; -use zeth_primitives::{block::Header, transactions::TxEssence, U256}; +use revm::{ + primitives::{calc_excess_blob_gas as calculate_excess_blob_gas, SpecId}, + Database, DatabaseCommit, +}; +use zeth_primitives::Header; use crate::{ builder::BlockBuilder, - consts::{Eip1559Constants, GAS_LIMIT_BOUND_DIVISOR, MAX_EXTRA_DATA_BYTES, MIN_GAS_LIMIT, ONE}, + consts::{Eip1559Constants, GAS_LIMIT_BOUND_DIVISOR, MAX_EXTRA_DATA_BYTES, MIN_GAS_LIMIT}, }; pub trait HeaderPrepStrategy { - fn prepare_header(block_builder: BlockBuilder) -> Result> + fn prepare_header(block_builder: BlockBuilder) -> Result> where D: Database + DatabaseCommit, - ::Error: core::fmt::Debug, - E: TxEssence; + ::Error: core::fmt::Debug; } pub struct EthHeaderPrepStrategy {} impl HeaderPrepStrategy for EthHeaderPrepStrategy { - fn prepare_header(mut block_builder: BlockBuilder) -> Result> + fn prepare_header(mut block_builder: BlockBuilder) -> Result> where D: Database + DatabaseCommit, ::Error: Debug, - E: TxEssence, { + let input = &block_builder.input.state_input; + // Validate gas limit - let diff = block_builder - .input - .state_input - .parent_header - .gas_limit - .abs_diff(block_builder.input.state_input.gas_limit); - let limit = - block_builder.input.state_input.parent_header.gas_limit / GAS_LIMIT_BOUND_DIVISOR; + let diff = input.parent_header.gas_limit.abs_diff(input.gas_limit); + let limit = input.parent_header.gas_limit / GAS_LIMIT_BOUND_DIVISOR; if diff >= limit { bail!( "Invalid gas limit: expected {} +- {}, got {}", - block_builder.input.state_input.parent_header.gas_limit, + input.parent_header.gas_limit, limit, - block_builder.input.state_input.gas_limit, + input.gas_limit, ); } - if block_builder.input.state_input.gas_limit < MIN_GAS_LIMIT { + if input.gas_limit < MIN_GAS_LIMIT { bail!( "Invalid gas limit: expected >= {}, got {}", MIN_GAS_LIMIT, - block_builder.input.state_input.gas_limit, + input.gas_limit, ); } // Validate timestamp - let timestamp = block_builder.input.state_input.timestamp; - if timestamp <= block_builder.input.state_input.parent_header.timestamp { + let timestamp = input.timestamp; + if timestamp <= input.parent_header.timestamp { bail!( "Invalid timestamp: expected > {}, got {}", - block_builder.input.state_input.parent_header.timestamp, - block_builder.input.state_input.timestamp, + input.parent_header.timestamp, + input.timestamp, ); } // Validate extra data - let extra_data_bytes = block_builder.input.state_input.extra_data.len(); + let extra_data_bytes = input.extra_data.len(); if extra_data_bytes > MAX_EXTRA_DATA_BYTES { bail!( "Invalid extra data: expected <= {}, got {}", @@ -83,38 +80,42 @@ impl HeaderPrepStrategy for EthHeaderPrepStrategy { ) } // Validate number - let parent_number = block_builder.input.state_input.parent_header.number; + let parent_number = input.parent_header.number; let number = parent_number .checked_add(1) .context("Invalid number: too large")?; - - // Derive fork version + // Validate fork version let spec_id = block_builder .chain_spec - .active_fork(number, ×tamp) + .active_fork(number, timestamp) .unwrap_or_else(|err| panic!("Invalid version: {:#}", err)); + // Validate `parent_beacon_block_root` + if spec_id >= SpecId::CANCUN && input.parent_beacon_block_root.is_none() { + bail!("Invalid beacon block root: missing") + } + block_builder.spec_id = Some(spec_id); // Derive header block_builder.header = Some(Header { // Initialize fields that we can compute from the parent - parent_hash: block_builder.input.state_input.parent_header.hash(), - number: block_builder - .input - .state_input - .parent_header - .number - .checked_add(1) - .context("Invalid block number: too large")?, - base_fee_per_gas: derive_base_fee( - &block_builder.input.state_input.parent_header, - block_builder.chain_spec.gas_constants(spec_id).unwrap(), - ), + parent_hash: input.parent_header.hash_slow(), + number, + base_fee_per_gas: (spec_id >= SpecId::LONDON).then(|| { + calc_base_fee_per_gas( + &input.parent_header, + block_builder.chain_spec.gas_constants(spec_id).unwrap(), + ) + }), + excess_blob_gas: (spec_id >= SpecId::CANCUN) + .then(|| calc_excess_blob_gas(&input.parent_header)), + // Initialize metadata from input - beneficiary: block_builder.input.state_input.beneficiary, - gas_limit: block_builder.input.state_input.gas_limit, + beneficiary: input.beneficiary, + gas_limit: input.gas_limit, timestamp, - mix_hash: block_builder.input.state_input.mix_hash, - extra_data: block_builder.input.state_input.extra_data.clone(), + mix_hash: input.mix_hash, + parent_beacon_block_root: input.parent_beacon_block_root, + extra_data: input.extra_data.clone(), // do not fill the remaining fields ..Default::default() }); @@ -123,35 +124,40 @@ impl HeaderPrepStrategy for EthHeaderPrepStrategy { } /// Base fee for next block. [EIP-1559](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-1559.md) spec -fn derive_base_fee(parent: &Header, eip_1559_constants: &Eip1559Constants) -> U256 { +fn calc_base_fee_per_gas(parent: &Header, eip_1559_constants: &Eip1559Constants) -> u64 { let parent_gas_target = parent.gas_limit / eip_1559_constants.elasticity_multiplier; + let parent_base_fee = parent.base_fee_per_gas.unwrap(); match parent.gas_used.cmp(&parent_gas_target) { - std::cmp::Ordering::Equal => parent.base_fee_per_gas, + std::cmp::Ordering::Equal => parent_base_fee, std::cmp::Ordering::Greater => { + // calculate the increase in base fee based on the formula defined by EIP-1559 let gas_used_delta = parent.gas_used - parent_gas_target; - let base_fee_delta = ONE - .max( - parent.base_fee_per_gas * gas_used_delta - / parent_gas_target - / eip_1559_constants.base_fee_change_denominator, - ) - .min( - parent.base_fee_per_gas / eip_1559_constants.base_fee_max_increase_denominator, - ); - parent.base_fee_per_gas + base_fee_delta + let base_fee_delta = 1u64.max( + (parent_base_fee as u128 * gas_used_delta as u128 + / (parent_gas_target as u128 + * eip_1559_constants.base_fee_change_denominator as u128)) + as u64, + ); + parent_base_fee + base_fee_delta } std::cmp::Ordering::Less => { + // calculate the decrease in base fee based on the formula defined by EIP-1559 let gas_used_delta = parent_gas_target - parent.gas_used; - let base_fee_delta = (parent.base_fee_per_gas * gas_used_delta - / parent_gas_target - / eip_1559_constants.base_fee_change_denominator) - .min( - parent.base_fee_per_gas / eip_1559_constants.base_fee_max_decrease_denominator, - ); - parent.base_fee_per_gas - base_fee_delta + let base_fee_delta = (parent_base_fee as u128 * gas_used_delta as u128 + / (parent_gas_target as u128 + * eip_1559_constants.base_fee_change_denominator as u128)) + as u64; + parent_base_fee.saturating_sub(base_fee_delta) } } } + +fn calc_excess_blob_gas(parent: &Header) -> u64 { + calculate_excess_blob_gas( + parent.excess_blob_gas.unwrap_or_default(), + parent.blob_gas_used.unwrap_or_default(), + ) +} diff --git a/lib/src/consts.rs b/lib/src/consts.rs index 947275d9..fd093527 100644 --- a/lib/src/consts.rs +++ b/lib/src/consts.rs @@ -21,7 +21,7 @@ use anyhow::{bail, Result}; use once_cell::sync::Lazy; use revm::primitives::SpecId; use serde::{Deserialize, Serialize}; -use zeth_primitives::{uint, BlockNumber, ChainId, U256}; +use zeth_primitives::{address, uint, Address, BlockNumber, ChainId, U256}; /// U256 representation of 0. pub const ZERO: U256 = U256::ZERO; @@ -29,9 +29,9 @@ pub const ZERO: U256 = U256::ZERO; pub const ONE: U256 = uint!(1_U256); /// The bound divisor of the gas limit, -pub const GAS_LIMIT_BOUND_DIVISOR: U256 = uint!(1024_U256); +pub const GAS_LIMIT_BOUND_DIVISOR: u64 = 1024; /// Minimum the gas limit may ever be. -pub const MIN_GAS_LIMIT: U256 = uint!(5000_U256); +pub const MIN_GAS_LIMIT: u64 = 5000; /// Maximum size of extra data. pub const MAX_EXTRA_DATA_BYTES: usize = 32; @@ -42,10 +42,14 @@ pub const MAX_BLOCK_HASH_AGE: u64 = 256; /// Multiplier for converting gwei to wei. pub const GWEI_TO_WEI: U256 = uint!(1_000_000_000_U256); +/// EIP-4788 constants. +pub const SYSTEM_ADDRESS: Address = address!("fffffffffffffffffffffffffffffffffffffffe"); +pub const BEACON_ROOTS_ADDRESS: Address = address!("000F3df6D732807Ef1319fB7B8bB8522d0Beac02"); + /// The Ethereum mainnet specification. pub static ETH_MAINNET_CHAIN_SPEC: Lazy = Lazy::new(|| ChainSpec { chain_id: 1, - max_spec_id: SpecId::SHANGHAI, + max_spec_id: SpecId::CANCUN, hard_forks: BTreeMap::from([ (SpecId::MERGE, ForkCondition::Block(15537394)), (SpecId::SHANGHAI, ForkCondition::Timestamp(1681338455)), @@ -56,10 +60,10 @@ pub static ETH_MAINNET_CHAIN_SPEC: Lazy = Lazy::new(|| ChainSpec { /// The Ethereum mainnet EIP-1559 gas constants. pub const ETH_MAINNET_EIP1559_CONSTANTS: Eip1559Constants = Eip1559Constants { - base_fee_change_denominator: uint!(8_U256), - base_fee_max_increase_denominator: uint!(8_U256), - base_fee_max_decrease_denominator: uint!(8_U256), - elasticity_multiplier: uint!(2_U256), + base_fee_change_denominator: 8, + base_fee_max_increase_denominator: 8, + base_fee_max_decrease_denominator: 8, + elasticity_multiplier: 2, }; /// The Optimism mainnet specification. @@ -79,19 +83,19 @@ pub static OP_MAINNET_CHAIN_SPEC: Lazy = Lazy::new(|| ChainSpec { ( SpecId::BEDROCK, Eip1559Constants { - base_fee_change_denominator: uint!(50_U256), - base_fee_max_increase_denominator: uint!(10_U256), - base_fee_max_decrease_denominator: uint!(50_U256), - elasticity_multiplier: uint!(6_U256), + base_fee_change_denominator: 50, + base_fee_max_increase_denominator: 10, + base_fee_max_decrease_denominator: 50, + elasticity_multiplier: 6, }, ), ( SpecId::CANYON, Eip1559Constants { - base_fee_change_denominator: uint!(250_U256), - base_fee_max_increase_denominator: uint!(10_U256), - base_fee_max_decrease_denominator: uint!(50_U256), - elasticity_multiplier: uint!(6_U256), + base_fee_change_denominator: 250, + base_fee_max_increase_denominator: 10, + base_fee_max_decrease_denominator: 50, + elasticity_multiplier: 6, }, ), ]), @@ -123,10 +127,10 @@ impl ForkCondition { /// [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) parameters. #[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)] pub struct Eip1559Constants { - pub base_fee_change_denominator: U256, - pub base_fee_max_increase_denominator: U256, - pub base_fee_max_decrease_denominator: U256, - pub elasticity_multiplier: U256, + pub base_fee_change_denominator: u64, + pub base_fee_max_increase_denominator: u64, + pub base_fee_max_decrease_denominator: u64, + pub elasticity_multiplier: u64, } /// Specification of a specific chain. @@ -156,10 +160,21 @@ impl ChainSpec { pub fn chain_id(&self) -> ChainId { self.chain_id } + /// Validates a [SpecId]. + pub fn validate_spec_id(&self, spec_id: SpecId) -> Result<()> { + let (min_spec_id, _) = self.hard_forks.first_key_value().unwrap(); + if spec_id < *min_spec_id { + bail!("expected >= {:?}, got {:?}", min_spec_id, spec_id); + } + if spec_id > self.max_spec_id { + bail!("expected <= {:?}, got {:?}", self.max_spec_id, spec_id); + } + Ok(()) + } /// Returns the [SpecId] for a given block number and timestamp or an error if not /// supported. - pub fn active_fork(&self, block_number: BlockNumber, timestamp: &U256) -> Result { - match self.spec_id(block_number, timestamp.saturating_to()) { + pub fn active_fork(&self, block_number: BlockNumber, timestamp: u64) -> Result { + match self.spec_id(block_number, timestamp) { Some(spec_id) => { if spec_id > self.max_spec_id { bail!("expected <= {:?}, got {:?}", self.max_spec_id, spec_id); diff --git a/lib/src/host/mpt.rs b/lib/src/host/mpt.rs index 4cf10465..457b585d 100644 --- a/lib/src/host/mpt.rs +++ b/lib/src/host/mpt.rs @@ -12,8 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::collections::HashMap; + use anyhow::{bail, Context, Result}; -use hashbrown::HashMap; use zeth_primitives::trie::{to_encoded_path, MptNode, MptNodeData, MptNodeReference}; /// Parses proof bytes into a vector of MPT nodes. diff --git a/lib/src/host/preflight.rs b/lib/src/host/preflight.rs index e64f38dc..f1681d4a 100644 --- a/lib/src/host/preflight.rs +++ b/lib/src/host/preflight.rs @@ -22,16 +22,15 @@ use anyhow::{anyhow, Context, Result}; use ethers_core::types::{ Block as EthersBlock, EIP1186ProofResponse, Transaction as EthersTransaction, }; -use hashbrown::{HashMap, HashSet}; use log::{debug, info}; +use revm::primitives::{HashMap, HashSet}; use zeth_primitives::{ - block::Header, - ethers::{from_ethers_h160, from_ethers_h256, from_ethers_u256}, + ethers::{from_ethers_block, from_ethers_h160, from_ethers_h256, from_ethers_u256}, keccak::keccak, - transactions::{Transaction, TxEssence}, + transactions::TxEnvelope, trie::{MptNode, MptNodeReference}, withdrawal::Withdrawal, - Address, B256, U256, + Address, Header, B256, U256, }; use crate::{ @@ -48,18 +47,18 @@ use crate::{ /// The initial data required to build a block as returned by the [Preflight]. #[derive(Debug, Clone)] -pub struct Data { +pub struct Data { pub db: MemDb, pub parent_header: Header, pub parent_proofs: HashMap, pub header: Option
, - pub transactions: Vec>, + pub transactions: Vec, pub withdrawals: Vec, pub proofs: HashMap, pub ancestor_headers: Vec
, } -pub trait Preflight { +pub trait Preflight { /// Executes the complete block using the input and state from the RPC provider. /// It returns all the data required to build and validate the block. fn preflight_with_external_data( @@ -67,27 +66,23 @@ pub trait Preflight { cache_path: Option, rpc_url: Option, block_no: u64, - ) -> Result>; + ) -> Result; fn preflight_with_local_data( chain_spec: &ChainSpec, provider_db: ProviderDb, - input: BlockBuildInput, - ) -> Result>; + input: BlockBuildInput, + ) -> Result; } /// Implements the [Preflight] trait for all compatible [BlockBuilderStrategy]s. -impl Preflight for N -where - N::TxEssence: TryFrom, - >::Error: Debug, -{ +impl Preflight for N { fn preflight_with_external_data( chain_spec: &ChainSpec, cache_path: Option, rpc_url: Option, block_no: u64, - ) -> Result> { + ) -> Result { let mut provider = new_provider(cache_path, rpc_url)?; // Fetch the parent block @@ -100,7 +95,8 @@ where parent_block.number.unwrap(), parent_block.hash.unwrap() ); - let parent_header: Header = parent_block.try_into().context("invalid parent block")?; + let parent_header: Header = + from_ethers_block(parent_block).context("invalid parent block")?; // Fetch the target block let block = provider.get_full_block(&BlockQuery { block_no })?; @@ -121,7 +117,8 @@ where // Create the block builder, run the transactions and extract the DB Self::preflight_with_local_data(chain_spec, provider_db, input).map( move |mut headerless_preflight_data| { - headerless_preflight_data.header = Some(block.try_into().expect("invalid block")); + headerless_preflight_data.header = + Some(from_ethers_block(block).expect("invalid block")); headerless_preflight_data }, ) @@ -130,8 +127,8 @@ where fn preflight_with_local_data( chain_spec: &ChainSpec, provider_db: ProviderDb, - input: BlockBuildInput, - ) -> Result> { + input: BlockBuildInput, + ) -> Result { let parent_header = input.state_input.parent_header.clone(); let transactions = input.state_input.transactions.clone(); let withdrawals = input.state_input.withdrawals.clone(); @@ -177,14 +174,10 @@ where } } -fn new_preflight_input( +fn new_preflight_input( block: EthersBlock, parent_header: Header, -) -> Result> -where - E: TxEssence + TryFrom, - >::Error: Debug, -{ +) -> Result { // convert each transaction let transactions = block .transactions @@ -211,12 +204,13 @@ where state_input: StateInput { parent_header, beneficiary: from_ethers_h160(block.author.context("author missing")?), - gas_limit: from_ethers_u256(block.gas_limit), - timestamp: from_ethers_u256(block.timestamp), + gas_limit: block.gas_limit.try_into().unwrap(), + timestamp: block.timestamp.try_into().unwrap(), extra_data: block.extra_data.0.into(), mix_hash: from_ethers_h256(block.mix_hash.context("mix_hash missing")?), transactions, withdrawals, + parent_beacon_block_root: block.parent_beacon_block_root.map(from_ethers_h256), }, parent_state_trie: Default::default(), parent_storage: Default::default(), @@ -228,10 +222,10 @@ where /// Converts the [Data] returned by the [Preflight] into /// [BlockBuildInput] required by the [BlockBuilder]. -impl TryFrom> for BlockBuildInput { +impl TryFrom for BlockBuildInput { type Error = anyhow::Error; - fn try_from(data: Data) -> Result> { + fn try_from(data: Data) -> Result { // collect the code from each account let mut contracts = HashSet::new(); for account in data.db.accounts.values() { @@ -269,6 +263,7 @@ impl TryFrom> for BlockBuildInput { mix_hash: header.mix_hash, transactions: data.transactions, withdrawals: data.withdrawals, + parent_beacon_block_root: header.parent_beacon_block_root, }, parent_state_trie: state_trie, parent_storage: storage, @@ -321,7 +316,7 @@ fn proofs_to_tries( continue; } - let mut storage_nodes = HashMap::new(); + let mut storage_nodes = std::collections::HashMap::new(); let mut storage_root_node = MptNode::default(); for storage_proof in &proof.storage_proof { let proof_nodes = @@ -340,7 +335,12 @@ fn proofs_to_tries( // assure that slots can be deleted from the storage trie for storage_proof in &fini_proofs.storage_proof { - add_orphaned_leafs(storage_proof.key, &storage_proof.proof, &mut storage_nodes)?; + let key = from_ethers_u256(storage_proof.key); + add_orphaned_leafs( + key.to_be_bytes::<32>(), + &storage_proof.proof, + &mut storage_nodes, + )?; } // create the storage trie, from all the relevant nodes let storage_trie = resolve_nodes(&storage_root_node, &storage_nodes); diff --git a/lib/src/host/provider_db.rs b/lib/src/host/provider_db.rs index 72a28230..ef2ea59d 100644 --- a/lib/src/host/provider_db.rs +++ b/lib/src/host/provider_db.rs @@ -17,15 +17,13 @@ extern crate alloc; use std::collections::BTreeSet; use ethers_core::types::{EIP1186ProofResponse, H160, H256}; -use hashbrown::HashMap; use revm::{ - primitives::{Account, AccountInfo, Bytecode}, + primitives::{Account, AccountInfo, Bytecode, HashMap}, Database, DatabaseCommit, }; use zeth_primitives::{ - block::Header, - ethers::{from_ethers_bytes, from_ethers_u256}, - Address, B256, U256, + ethers::{from_ethers_block, from_ethers_bytes, from_ethers_u256}, + Address, Header, B256, U256, }; use crate::{ @@ -121,11 +119,12 @@ impl ProviderDb { let headers = (*earliest_block..self.block_no) .rev() .map(|block_no| { - self.provider - .get_partial_block(&BlockQuery { block_no }) - .expect("Failed to retrieve ancestor block") - .try_into() - .expect("Failed to convert ethers block to zeth block") + from_ethers_block( + self.provider + .get_partial_block(&BlockQuery { block_no }) + .expect("Failed to retrieve ancestor block"), + ) + .expect("Failed to convert ethers block to zeth block") }) .collect(); Ok(headers) diff --git a/lib/src/host/rpc_db.rs b/lib/src/host/rpc_db.rs index 2a4cba0b..97c859c8 100644 --- a/lib/src/host/rpc_db.rs +++ b/lib/src/host/rpc_db.rs @@ -12,14 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::path::{Path, PathBuf}; +use std::{ + mem, + path::{Path, PathBuf}, +}; use anyhow::Context; -use zeth_primitives::{ - block::Header, - transactions::{ethereum::EthereumTxEssence, optimism::OptimismTxEssence}, - Address, -}; +use zeth_primitives::{ethers::from_ethers_block, Address, Header}; use crate::{ host::provider::{new_provider, BlockQuery}, @@ -85,24 +84,21 @@ impl BatcherDb for RpcDb { Ok(()) } - fn get_full_op_block( - &mut self, - block_no: u64, - ) -> anyhow::Result> { + fn get_full_op_block(&mut self, block_no: u64) -> anyhow::Result { let mut provider = new_provider( op_cache_path(&self.cache, block_no), self.op_rpc_url.clone(), ) .context("failed to create provider")?; let block = { - let ethers_block = provider.get_full_block(&BlockQuery { block_no })?; + let mut ethers_block = provider.get_full_block(&BlockQuery { block_no })?; + let transactions = mem::take(&mut ethers_block.transactions) + .into_iter() + .map(|tx| tx.try_into().unwrap()) + .collect(); BlockInput { - block_header: ethers_block.clone().try_into().unwrap(), - transactions: ethers_block - .transactions - .into_iter() - .map(|tx| tx.try_into().unwrap()) - .collect(), + block_header: from_ethers_block(ethers_block).unwrap(), + transactions, receipts: None, } }; @@ -116,18 +112,13 @@ impl BatcherDb for RpcDb { op_cache_path(&self.cache, block_no), self.op_rpc_url.clone(), )?; - let header: Header = provider - .get_partial_block(&BlockQuery { block_no })? - .try_into()?; + let header = from_ethers_block(provider.get_partial_block(&BlockQuery { block_no })?)?; self.mem_db.op_block_header.insert(block_no, header.clone()); provider.save()?; Ok(header) } - fn get_full_eth_block( - &mut self, - block_no: u64, - ) -> anyhow::Result<&BlockInput> { + fn get_full_eth_block(&mut self, block_no: u64) -> anyhow::Result<&BlockInput> { let query = BlockQuery { block_no }; let mut provider = new_provider( eth_cache_path(&self.cache, block_no), @@ -135,7 +126,7 @@ impl BatcherDb for RpcDb { )?; let block = { let ethers_block = provider.get_full_block(&query)?; - let block_header: Header = ethers_block.clone().try_into().unwrap(); + let block_header = from_ethers_block(ethers_block.clone()).unwrap(); // include receipts when needed let can_contain_deposits = deposits::can_contain(&self.deposit_contract, &block_header.logs_bloom); diff --git a/lib/src/host/verify.rs b/lib/src/host/verify.rs index 391961e6..e79deef6 100644 --- a/lib/src/host/verify.rs +++ b/lib/src/host/verify.rs @@ -14,14 +14,12 @@ use anyhow::{bail, Context, Result}; use ethers_core::types::EIP1186ProofResponse; -use hashbrown::HashMap; use log::error; +use revm::primitives::HashMap; use zeth_primitives::{ - block::Header, keccak::keccak, - transactions::TxEssence, trie::{Error as TrieError, MptNode, StateAccount}, - Address, B256, U256, + Address, Header, B256, U256, }; use super::{mpt, preflight}; @@ -63,7 +61,7 @@ pub trait Verifier { } /// Verify using the preflight data. -impl Verifier for preflight::Data { +impl Verifier for preflight::Data { fn verify_block(&self, header: &Header, state: &MptNode) -> Result<()> { let errors = verify_state_trie(state, &self.proofs).context("failed to verify state trie")?; @@ -117,7 +115,7 @@ fn verify_header(header: &Header, exp_header: &Header) -> Result<()> { if header.base_fee_per_gas != exp_header.base_fee_per_gas { error!( - "Base fee mismatch {} (expected {})", + "Base fee mismatch {:?} (expected {:?})", header.base_fee_per_gas, exp_header.base_fee_per_gas ); } @@ -129,8 +127,8 @@ fn verify_header(header: &Header, exp_header: &Header) -> Result<()> { ); } - let found_hash = header.hash(); - let expected_hash = exp_header.hash(); + let found_hash = header.hash_slow(); + let expected_hash = exp_header.hash_slow(); if found_hash.as_slice() != expected_hash.as_slice() { error!( "Final block hash mismatch {} (expected {})", diff --git a/lib/src/input.rs b/lib/src/input.rs index 528f80bc..8f93dd47 100644 --- a/lib/src/input.rs +++ b/lib/src/input.rs @@ -14,15 +14,12 @@ use alloy_rlp_derive::RlpEncodable; use ethers_core::k256::sha2::{Digest, Sha256}; -use hashbrown::HashMap; +use revm::primitives::HashMap; use serde::{Deserialize, Serialize}; +use serde_with::serde_as; use zeth_primitives::{ - block::Header, - mmr::Hash, - transactions::{Transaction, TxEssence}, - trie::MptNode, - withdrawal::Withdrawal, - Address, Bytes, B256, U256, + mmr::Hash, serde_with::RlpBytes, transactions::TxEnvelope, trie::MptNode, + withdrawal::Withdrawal, Address, Bytes, Header, B256, U256, }; /// Represents the state of an account's storage. @@ -31,10 +28,11 @@ use zeth_primitives::{ pub type StorageEntry = (MptNode, Vec); /// External block input. +#[serde_as] #[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] -pub struct BlockBuildInput { +pub struct BlockBuildInput { /// Block and transaction data to execute - pub state_input: StateInput, + pub state_input: StateInput, /// State trie of the parent block. pub parent_state_trie: MptNode, /// Maps each address with its storage trie and the used storage slots. @@ -42,30 +40,35 @@ pub struct BlockBuildInput { /// The code of all unique contracts. pub contracts: Vec, /// List of at most 256 previous block headers + #[serde_as(as = "Vec")] pub ancestor_headers: Vec
, } +#[serde_as] #[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize, RlpEncodable)] -pub struct StateInput { +#[rlp(trailing)] +pub struct StateInput { /// Previous block header + #[serde_as(as = "RlpBytes")] pub parent_header: Header, /// Address to which all priority fees in this block are transferred. pub beneficiary: Address, /// Scalar equal to the current limit of gas expenditure per block. - pub gas_limit: U256, + pub gas_limit: u64, /// Scalar corresponding to the seconds since Epoch at this block's inception. - pub timestamp: U256, + pub timestamp: u64, /// Arbitrary byte array containing data relevant for this block. pub extra_data: Bytes, /// Hash previously used for the PoW now containing the RANDAO value. pub mix_hash: B256, /// List of transactions for execution - pub transactions: Vec>, + pub transactions: Vec, /// List of stake withdrawals for execution pub withdrawals: Vec, + pub parent_beacon_block_root: Option, } -impl StateInput { +impl StateInput { pub fn hash(&self) -> Hash { let mut hasher = Sha256::new(); hasher.update(&alloy_rlp::encode(self)); @@ -75,29 +78,12 @@ impl StateInput { #[cfg(test)] mod tests { - use zeth_primitives::transactions::ethereum::EthereumTxEssence; - use super::*; #[test] fn input_serde_roundtrip() { - let input = BlockBuildInput { - state_input: StateInput:: { - parent_header: Default::default(), - beneficiary: Default::default(), - gas_limit: Default::default(), - timestamp: Default::default(), - extra_data: Default::default(), - mix_hash: Default::default(), - transactions: vec![], - withdrawals: vec![], - }, - parent_state_trie: Default::default(), - parent_storage: Default::default(), - contracts: vec![], - ancestor_headers: vec![], - }; - let _: BlockBuildInput = + let input: BlockBuildInput = Default::default(); + let _: BlockBuildInput = bincode::deserialize(&bincode::serialize(&input).unwrap()).unwrap(); } } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 9f3a0da4..f1ceaf17 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -26,8 +26,6 @@ pub mod output; mod utils; -pub use zeth_primitives::transactions::{ethereum::EthereumTxEssence, optimism::OptimismTxEssence}; - /// call forget only if running inside the guest pub fn guest_mem_forget(_t: T) { #[cfg(target_os = "zkvm")] diff --git a/lib/src/mem_db.rs b/lib/src/mem_db.rs index b84b88c6..1f99daef 100644 --- a/lib/src/mem_db.rs +++ b/lib/src/mem_db.rs @@ -13,9 +13,8 @@ // limitations under the License. use anyhow::anyhow; -use hashbrown::{hash_map::Entry, HashMap}; use revm::{ - primitives::{Account, AccountInfo, Bytecode}, + primitives::{hash_map::Entry, Account, AccountInfo, Bytecode, HashMap}, Database, DatabaseCommit, }; use thiserror::Error as ThisError; @@ -200,9 +199,6 @@ impl DatabaseCommit for MemDb { } }; - // it is not possible to delete a deleted account - debug_assert!(db_account.state != AccountState::Deleted); - // clear the account and mark it as deleted db_account.storage.clear(); db_account.state = AccountState::Deleted; diff --git a/lib/src/optimism/batcher.rs b/lib/src/optimism/batcher.rs index 0166f58e..dba1da02 100644 --- a/lib/src/optimism/batcher.rs +++ b/lib/src/optimism/batcher.rs @@ -20,12 +20,8 @@ use revm::primitives::SpecId; use serde::{Deserialize, Serialize}; use zeth_primitives::{ batch::{Batch, BatchEssence}, - transactions::{ - ethereum::EthereumTxEssence, - optimism::{OptimismTxEssence, OPTIMISM_DEPOSITED_TX_TYPE}, - Transaction, - }, - BlockHash, BlockNumber, U256, + transactions::{optimism::OPTIMISM_DEPOSITED_TX_TYPE, TxEnvelope}, + BlockHash, BlockNumber, }; use super::{ @@ -50,8 +46,8 @@ pub struct Epoch { pub number: BlockNumber, pub hash: BlockHash, pub timestamp: u64, - pub base_fee_per_gas: U256, - pub deposits: Vec>, + pub base_fee_per_gas: u64, + pub deposits: Vec, } #[derive(Debug, Clone, Default)] @@ -137,17 +133,13 @@ pub struct Batcher { } impl Batcher { - pub fn new( - config: ChainConfig, - op_head: L2BlockInfo, - eth_block: &BlockInput, - ) -> Result { + pub fn new(config: ChainConfig, op_head: L2BlockInfo, eth_block: &BlockInput) -> Result { let timestamp = eth_block.block_header.timestamp; - let spec_id = config.chain_spec.active_fork(0, ×tamp)?; + let spec_id = config.chain_spec.active_fork(0, timestamp)?; let batcher_channel = BatcherChannels::new(&config, spec_id); - let eth_block_hash = eth_block.block_header.hash(); + let eth_block_hash = eth_block.block_header.hash_slow(); let state = State::new( eth_block.block_header.number, eth_block_hash, @@ -155,8 +147,8 @@ impl Batcher { Epoch { number: eth_block.block_header.number, hash: eth_block_hash, - timestamp: timestamp.try_into().unwrap(), - base_fee_per_gas: eth_block.block_header.base_fee_per_gas, + timestamp, + base_fee_per_gas: eth_block.block_header.base_fee_per_gas.unwrap(), deposits: deposits::extract_transactions(&config, eth_block)?, }, ); @@ -175,8 +167,8 @@ impl Batcher { &self.config } - pub fn process_l1_block(&mut self, eth_block: &BlockInput) -> Result<()> { - let eth_block_hash = eth_block.block_header.hash(); + pub fn process_l1_block(&mut self, eth_block: &BlockInput) -> Result<()> { + let eth_block_hash = eth_block.block_header.hash_slow(); // Ensure block has correct parent ensure!( @@ -188,7 +180,7 @@ impl Batcher { self.spec_id = self .config .chain_spec - .active_fork(0, ð_block.block_header.timestamp)?; + .active_fork(0, eth_block.block_header.timestamp)?; if eth_block.receipts.is_some() { // Update the system config. From the spec: @@ -205,8 +197,8 @@ impl Batcher { self.state.push_epoch(Epoch { number: eth_block.block_header.number, hash: eth_block_hash, - timestamp: eth_block.block_header.timestamp.try_into().unwrap(), - base_fee_per_gas: eth_block.block_header.base_fee_per_gas, + timestamp: eth_block.block_header.timestamp, + base_fee_per_gas: eth_block.block_header.base_fee_per_gas.unwrap(), deposits: deposits::extract_transactions(&self.config, eth_block)?, })?; diff --git a/lib/src/optimism/batcher_channel.rs b/lib/src/optimism/batcher_channel.rs index cf8c14df..a27684ec 100644 --- a/lib/src/optimism/batcher_channel.rs +++ b/lib/src/optimism/batcher_channel.rs @@ -24,8 +24,8 @@ use revm::primitives::SpecId; use zeth_primitives::{ alloy_rlp::Decodable, batch::Batch, - transactions::{ethereum::EthereumTxEssence, Transaction, TxEssence}, - Address, BlockNumber, + transactions::{EvmTransaction, TxEnvelope}, + Address, BlockNumber, TxKind, }; use super::{batcher::BatchWithInclusion, config::ChainConfig}; @@ -61,18 +61,18 @@ impl BatcherChannels { &mut self, batch_sender: Address, block_number: BlockNumber, - transactions: &Vec>, + transactions: &Vec, ) -> Result<()> { for tx in transactions { // From the spec: // "The receiver must be the configured batcher inbox address." - if tx.essence.to() != Some(self.batch_inbox) { + if tx.to() != TxKind::Call(self.batch_inbox) { continue; } // From the spec: // "The sender must match the batcher address loaded from the system config matching // the L1 block of the data." - if tx.recover_from().context("invalid signature")? != batch_sender { + if tx.from().context("invalid signature")? != batch_sender { continue; } @@ -81,7 +81,7 @@ impl BatcherChannels { // From the spec: // "If any one frame fails to parse, the all frames in the transaction are rejected." - let frames = match Frame::process_batcher_transaction(&tx.essence) { + let frames = match Frame::process_batcher_transaction(tx) { Ok(frames) => frames, Err(_err) => { #[cfg(not(target_os = "zkvm"))] @@ -380,9 +380,9 @@ impl Frame { const MAX_FRAME_DATA_LENGTH: u32 = 1_000_000; /// Processes a batcher transaction and returns the list of contained frames. - pub fn process_batcher_transaction(tx_essence: &EthereumTxEssence) -> Result> { + pub fn process_batcher_transaction(tx_essence: &TxEnvelope) -> Result> { let (version, mut rollup_payload) = tx_essence - .data() + .input() .split_first() .context("empty transaction data")?; ensure!(version == &0, "invalid transaction version: {}", version); diff --git a/lib/src/optimism/batcher_db.rs b/lib/src/optimism/batcher_db.rs index 284927c1..ef45f581 100644 --- a/lib/src/optimism/batcher_db.rs +++ b/lib/src/optimism/batcher_db.rs @@ -16,41 +16,42 @@ use std::collections::HashMap; use anyhow::{ensure, Context, Result}; use serde::{Deserialize, Serialize}; +use serde_with::serde_as; use zeth_primitives::{ - alloy_rlp, - block::Header, - receipt::Receipt, - transactions::{ - ethereum::EthereumTxEssence, optimism::OptimismTxEssence, Transaction, TxEssence, - }, - trie::MptNode, + alloy_rlp, receipt::ReceiptEnvelope, serde_with::RlpBytes, transactions::TxEnvelope, + trie::MptNode, Header, }; use super::{config::ChainConfig, deposits, system_config}; /// Input for extracting deposits. +#[serde_as] #[derive(Debug, Clone, Deserialize, Serialize)] -pub struct BlockInput { +pub struct BlockInput { /// Header of the block. + #[serde_as(as = "RlpBytes")] pub block_header: Header, /// Transactions of the block. - pub transactions: Vec>, + pub transactions: Vec, /// Transaction receipts of the block or `None` if not required. - pub receipts: Option>, + pub receipts: Option>, } pub trait BatcherDb { fn validate(&self, config: &ChainConfig) -> Result<()>; - fn get_full_op_block(&mut self, block_no: u64) -> Result>; + fn get_full_op_block(&mut self, block_no: u64) -> Result; fn get_op_block_header(&mut self, block_no: u64) -> Result
; - fn get_full_eth_block(&mut self, block_no: u64) -> Result<&BlockInput>; + fn get_full_eth_block(&mut self, block_no: u64) -> Result<&BlockInput>; } +#[serde_as] #[derive(Debug, Clone, Deserialize, Serialize)] pub struct MemDb { - pub full_op_block: HashMap>, + pub full_op_block: HashMap, + #[serde_as(as = "HashMap<_, RlpBytes>")] pub op_block_header: HashMap, - pub full_eth_block: HashMap>, + pub full_eth_block: HashMap, + #[serde_as(as = "HashMap<_, RlpBytes>")] pub eth_block_header: HashMap, } @@ -145,7 +146,7 @@ impl BatcherDb for MemDb { Ok(()) } - fn get_full_op_block(&mut self, block_no: u64) -> Result> { + fn get_full_op_block(&mut self, block_no: u64) -> Result { let op_block = self.full_op_block.remove(&block_no).unwrap(); Ok(op_block) @@ -160,7 +161,7 @@ impl BatcherDb for MemDb { Ok(op_block) } - fn get_full_eth_block(&mut self, block_no: u64) -> Result<&BlockInput> { + fn get_full_eth_block(&mut self, block_no: u64) -> Result<&BlockInput> { let eth_block = self.full_eth_block.get(&block_no).unwrap(); Ok(eth_block) diff --git a/lib/src/optimism/composition.rs b/lib/src/optimism/composition.rs index 33cfba92..5832d051 100644 --- a/lib/src/optimism/composition.rs +++ b/lib/src/optimism/composition.rs @@ -16,10 +16,12 @@ use anyhow::bail; #[cfg(target_os = "zkvm")] use risc0_zkvm::{guest::env, serde::to_vec, sha::Digest}; use serde::{Deserialize, Serialize}; +use serde_with::serde_as; use zeth_primitives::{ - block::Header, mmr, mmr::{MerkleMountainRange, MerkleProof}, + serde_with::RlpBytes, + Header, }; use crate::optimism::{batcher::BlockId, DeriveOutput}; @@ -44,6 +46,7 @@ pub struct ComposeInput { pub eth_chain_merkle_root: mmr::Hash, } +#[serde_as] #[derive(Debug, Clone, Deserialize, Serialize)] pub enum ComposeInputOperation { /// Takes a chain of ethereum blocks and inserts them into a Merkle-tree, @@ -52,6 +55,7 @@ pub enum ComposeInputOperation { /// mountain range (and corresponding proof) as input if the ethereum chain /// is too large for one session. PREP { + #[serde_as(as = "Vec")] eth_blocks: Vec
, prior_prep: Option<(ComposeOutput, MerkleMountainRange)>, }, @@ -161,7 +165,7 @@ impl ComposeInput { assert_eq!(block.parent_hash, parent_hash); } // Derive block's keccak hash - let block_hash = block.hash(); + let block_hash = block.hash_slow(); // Insert hash into mountain range mountain_range.append_leaf(block_hash.0, None); // Mark block as new tail diff --git a/lib/src/optimism/config.rs b/lib/src/optimism/config.rs index b442a4f7..63907f1e 100644 --- a/lib/src/optimism/config.rs +++ b/lib/src/optimism/config.rs @@ -55,7 +55,7 @@ impl ChainConfig { Self { system_config: SystemConfig { batch_sender: address!("6887246668a3b87f54deb3b94ba47a6f63f32985"), - gas_limit: uint!(30_000_000_U256), + gas_limit: 30_000_000_u64, l1_fee_overhead: uint!(188_U256), l1_fee_scalar: uint!(684000_U256), unsafe_block_signer: address!("AAAA45d9549EDA09E70937013520214382Ffc4A2"), diff --git a/lib/src/optimism/deposits.rs b/lib/src/optimism/deposits.rs index 76804f72..6d12e2c6 100644 --- a/lib/src/optimism/deposits.rs +++ b/lib/src/optimism/deposits.rs @@ -16,13 +16,9 @@ use alloy_sol_types::{sol_data, SolType}; use anyhow::{ensure, Context}; use zeth_primitives::{ fixed_bytes, keccak256, - receipt::Log, - transactions::{ - ethereum::{EthereumTxEssence, TransactionKind}, - optimism::{OptimismTxEssence, TxEssenceOptimismDeposited}, - Transaction, - }, - Address, Bloom, BloomInput, B256, U160, U256, + receipt::EvmReceipt, + transactions::{optimism::TxOptimismDeposit, TxEnvelope}, + Address, Bloom, BloomInput, Log, B256, U160, U256, }; use super::{batcher_db::BlockInput, config::ChainConfig}; @@ -37,9 +33,9 @@ const TRANSACTION_DEPOSITED_VERSION: B256 = B256::ZERO; /// Extracts deposits from the given block. pub fn extract_transactions( config: &ChainConfig, - input: &BlockInput, -) -> anyhow::Result>> { - let block_hash = input.block_header.hash(); + input: &BlockInput, +) -> anyhow::Result> { + let block_hash = input.block_header.hash_slow(); // if the bloom filter does not contain the corresponding topics, we have the guarantee // that there are no deposits in the block @@ -53,11 +49,9 @@ pub fn extract_transactions( let mut log_index = 0_usize; for receipt in receipts { - let receipt = &receipt.payload; - // skip failed transactions - if !receipt.success { - log_index += receipt.logs.len(); + if !receipt.success() { + log_index += receipt.logs().len(); continue; } // we could skip the transaction if the Bloom filter does not contain the deposit log, but @@ -65,9 +59,9 @@ pub fn extract_transactions( // logs // parse all the logs for deposit transactions - for log in &receipt.logs { + for log in receipt.logs() { if log.address == config.deposit_contract - && log.topics[0] == TRANSACTION_DEPOSITED_SIGNATURE + && log.data.topics()[0] == TRANSACTION_DEPOSITED_SIGNATURE { deposits.push( to_deposit_transaction(block_hash, log_index, log) @@ -100,30 +94,33 @@ fn to_deposit_transaction( block_hash: B256, log_index: usize, log: &Log, -) -> anyhow::Result> { - let from = U160::try_from_be_slice(&log.topics[1][12..]) +) -> anyhow::Result { + let from = U160::try_from_be_slice(&log.data.topics()[1][12..]) .context("invalid from")? .into(); - let to = U160::try_from_be_slice(&log.topics[2][12..]) + let to: Address = U160::try_from_be_slice(&log.data.topics()[2][12..]) .context("invalid to")? .into(); // TODO: it is not 100% defined, what happens if the version is not 0 // it is assumed that this is an error and must not be ignored ensure!( - log.topics[3] == TRANSACTION_DEPOSITED_VERSION, + log.data.topics()[3] == TRANSACTION_DEPOSITED_VERSION, "invalid version" ); // the log data is just an ABI encoded `bytes` type representing the opaque_data let opaque_data: Vec = - sol_data::Bytes::abi_decode(&log.data, true).context("invalid data")?; + sol_data::Bytes::abi_decode(&log.data.data, true).context("invalid data")?; ensure!(opaque_data.len() >= 73, "invalid opaque_data"); let mint = U256::try_from_be_slice(&opaque_data[0..32]).context("invalid mint")?; let value = U256::try_from_be_slice(&opaque_data[32..64]).context("invalid value")?; - let gas_limit = U256::try_from_be_slice(&opaque_data[64..72]).context("invalid gas_limit")?; - let is_creation = opaque_data[72] != 0; + let gas_limit: u64 = U256::try_from_be_slice(&opaque_data[64..72]) + .unwrap() + .try_into() + .context("invalid gas_limit")?; + let is_call = opaque_data[72] == 0; let data = opaque_data[73..].to_vec(); // compute the source hash @@ -131,23 +128,14 @@ fn to_deposit_transaction( let source_hash = keccak256([U256::from(0).to_be_bytes(), h.0].concat()); // construct the transaction - let essence = OptimismTxEssence::OptimismDeposited(TxEssenceOptimismDeposited { + Ok(TxEnvelope::OptimismDeposit(TxOptimismDeposit { source_hash, from, - to: if is_creation { - TransactionKind::Create - } else { - TransactionKind::Call(to) - }, + to: is_call.then_some(to).into(), mint, value, gas_limit, is_system_tx: false, - data: data.into(), - }); - - Ok(Transaction { - essence, - signature: Default::default(), - }) + input: data.into(), + })) } diff --git a/lib/src/optimism/mod.rs b/lib/src/optimism/mod.rs index 9ea5f86a..5be9b887 100644 --- a/lib/src/optimism/mod.rs +++ b/lib/src/optimism/mod.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use core::iter::once; +use std::{iter::once, mem}; use alloy_sol_types::{sol, SolInterface}; use anyhow::{bail, ensure, Context, Result}; @@ -22,15 +22,10 @@ use serde::{Deserialize, Serialize}; use zeth_primitives::{ alloy_rlp, batch::Batch, - block::Header, keccak::keccak, - transactions::{ - ethereum::TransactionKind, - optimism::{OptimismTxEssence, TxEssenceOptimismDeposited}, - Transaction, TxEssence, - }, + transactions::{optimism::TxOptimismDeposit, EvmTransaction, TxEnvelope}, trie::MptNode, - uint, Address, FixedBytes, RlpBytes, B256, U256, + Address, FixedBytes, Header, RlpBytes, B256, U256, }; #[cfg(not(target_os = "zkvm"))] @@ -138,7 +133,7 @@ impl DeriveMachine { let op_head = derive_input .db .get_full_op_block(derive_input.op_head_block_no)?; - let op_head_block_hash = op_head.block_header.hash(); + let op_head_block_hash = op_head.block_header.hash_slow(); #[cfg(not(target_os = "zkvm"))] log::debug!( @@ -148,11 +143,7 @@ impl DeriveMachine { ); // the first transaction in a block MUST be a L1 attributes deposited transaction - let l1_attributes_tx = &op_head - .transactions - .first() - .context("block is empty")? - .essence; + let l1_attributes_tx = &op_head.transactions.first().context("block is empty")?; if let Err(err) = validate_l1_attributes_deposited_tx(&chain_config, l1_attributes_tx) { bail!( "First transaction in block is not a valid L1 attributes deposited transaction: {}", @@ -161,7 +152,7 @@ impl DeriveMachine { } // decode the L1 attributes deposited transaction let set_l1_block_values = { - let call = OpSystemInfo::OpSystemInfoCalls::abi_decode(l1_attributes_tx.data(), true) + let call = OpSystemInfo::OpSystemInfoCalls::abi_decode(l1_attributes_tx.input(), true) .context("invalid L1 attributes data")?; match call { OpSystemInfo::OpSystemInfoCalls::setL1BlockValues(x) => x, @@ -174,7 +165,7 @@ impl DeriveMachine { let eth_block_no = set_l1_block_values.number; let eth_head = derive_input.db.get_full_eth_block(eth_block_no)?; ensure!( - eth_head.block_header.hash() == set_l1_block_values.hash, + eth_head.block_header.hash_slow() == set_l1_block_values.hash, "Ethereum head block hash mismatch" ); #[cfg(not(target_os = "zkvm"))] @@ -194,7 +185,7 @@ impl DeriveMachine { chain_config, L2BlockInfo { hash: op_head_block_hash, - timestamp: op_head.block_header.timestamp.try_into().unwrap(), + timestamp: op_head.block_header.timestamp, l1_origin: BlockId { number: set_l1_block_values.number, hash: set_l1_block_values.hash, @@ -215,7 +206,7 @@ impl DeriveMachine { pub fn derive( &mut self, - mut op_block_inputs: Option<&mut Vec>>, + mut op_block_inputs: Option<&mut Vec>, ) -> Result { #[cfg(target_os = "zkvm")] op_block_inputs.take(); @@ -230,7 +221,7 @@ impl DeriveMachine { // Save starting op_head let op_head = BlockId { number: self.op_head_block_header.number, - hash: self.op_head_block_header.hash(), + hash: self.op_head_block_header.hash_slow(), }; let mut derived_op_blocks = Vec::new(); @@ -283,7 +274,7 @@ impl DeriveMachine { self.op_block_seq_no = 0; self.op_batcher.state.do_next_epoch()?; - self.op_batcher.state.epoch.deposits.clone() + mem::take(&mut self.op_batcher.state.epoch.deposits) } else { self.op_block_seq_no += 1; @@ -306,7 +297,7 @@ impl DeriveMachine { let mut decoded_batch_transactions = vec![]; let mut decoding_error = false; for raw_tx in &op_batch.0.transactions { - match Transaction::::decode_bytes(raw_tx) { + match TxEnvelope::decode_bytes(raw_tx) { Ok(tx) => { decoded_batch_transactions.push(tx); } @@ -322,10 +313,11 @@ impl DeriveMachine { continue; } - let derived_transactions: Vec<_> = once(l1_attributes_tx) - .chain(deposits) - .chain(decoded_batch_transactions) - .collect(); + let derived_transactions: Vec<_> = + once(TxEnvelope::OptimismDeposit(l1_attributes_tx)) + .chain(deposits) + .chain(decoded_batch_transactions) + .collect(); let derived_transactions_rlp = derived_transactions .iter() .map(alloy_rlp::encode) @@ -341,11 +333,10 @@ impl DeriveMachine { parent_header: self.op_head_block_header.clone(), beneficiary: self.op_batcher.config().sequencer_fee_vault, gas_limit: self.op_batcher.config().system_config.gas_limit, - timestamp: U256::from(op_batch.0.timestamp), - extra_data: Default::default(), + timestamp: op_batch.0.timestamp, mix_hash: l1_epoch_header_mix_hash, transactions: derived_transactions, - withdrawals: vec![], + ..Default::default() }, // initializing these fields is not needed here parent_state_trie: Default::default(), @@ -386,8 +377,7 @@ impl DeriveMachine { headerless_preflight_data })?; - let executable_input: BlockBuildInput = - preflight_data.try_into()?; + let executable_input: BlockBuildInput = preflight_data.try_into()?; if let Some(ref mut inputs_vec) = op_block_inputs { inputs_vec.push(executable_input.clone()); } @@ -432,7 +422,7 @@ impl DeriveMachine { self.op_batcher.state.safe_head = L2BlockInfo { hash: new_block_hash, - timestamp: new_block_head.timestamp.try_into().unwrap(), + timestamp: new_block_head.timestamp, l1_origin: BlockId { number: self.op_batcher.state.epoch.number, hash: self.op_batcher.state.epoch.hash, @@ -468,10 +458,7 @@ impl DeriveMachine { }) } - fn derive_l1_attributes_deposited_tx( - &mut self, - op_batch: &Batch, - ) -> Transaction { + fn derive_l1_attributes_deposited_tx(&mut self, op_batch: &Batch) -> TxOptimismDeposit { let batcher_hash = { let all_zero: FixedBytes<12> = FixedBytes::ZERO; all_zero.concat_const::<20, 32>(self.op_batcher.config().system_config.batch_sender.0) @@ -481,7 +468,7 @@ impl DeriveMachine { OpSystemInfo::OpSystemInfoCalls::setL1BlockValues(OpSystemInfo::setL1BlockValuesCall { number: self.op_batcher.state.epoch.number, timestamp: self.op_batcher.state.epoch.timestamp, - basefee: self.op_batcher.state.epoch.base_fee_per_gas, + basefee: U256::from(self.op_batcher.state.epoch.base_fee_per_gas), hash: self.op_batcher.state.epoch.hash, sequence_number: self.op_block_seq_no, batcher_hash, @@ -497,41 +484,36 @@ impl DeriveMachine { }; let config = self.op_batcher.config(); - Transaction { - essence: OptimismTxEssence::OptimismDeposited(TxEssenceOptimismDeposited { - source_hash, - from: config.l1_attributes_depositor, - to: TransactionKind::Call(config.l1_attributes_contract), - mint: Default::default(), - value: Default::default(), - gas_limit: uint!(1_000_000_U256), - is_system_tx: false, - data: set_l1_block_values.abi_encode().into(), - }), - signature: Default::default(), + TxOptimismDeposit { + source_hash, + from: config.l1_attributes_depositor, + to: config.l1_attributes_contract.into(), + mint: Default::default(), + value: Default::default(), + gas_limit: 1_000_000_u64, + is_system_tx: false, + input: set_l1_block_values.abi_encode().into(), } } } -fn validate_l1_attributes_deposited_tx(config: &ChainConfig, tx: &OptimismTxEssence) -> Result<()> { +fn validate_l1_attributes_deposited_tx(config: &ChainConfig, tx: &TxEnvelope) -> Result<()> { match tx { - OptimismTxEssence::Ethereum(_) => { - bail!("No Optimism deposit transaction"); - } - OptimismTxEssence::OptimismDeposited(op) => { + TxEnvelope::OptimismDeposit(op) => { ensure!( op.from == config.l1_attributes_depositor, "Invalid from address" ); ensure!( - matches!(op.to, TransactionKind::Call(addr) if addr == config.l1_attributes_contract), + op.to.to() == Some(config.l1_attributes_contract), "Invalid to address" ); ensure!(op.mint == U256::ZERO, "Invalid mint value"); ensure!(op.value == U256::ZERO, "Invalid value"); - ensure!(op.gas_limit == uint!(1_000_000_U256), "Invalid gas limit"); + ensure!(op.gas_limit == 1_000_000_u64, "Invalid gas limit"); ensure!(!op.is_system_tx, "Invalid is_system_tx value"); } + _ => bail!("Invalid transaction type"), } Ok(()) diff --git a/lib/src/optimism/system_config.rs b/lib/src/optimism/system_config.rs index d5574165..21642a68 100644 --- a/lib/src/optimism/system_config.rs +++ b/lib/src/optimism/system_config.rs @@ -14,9 +14,7 @@ use anyhow::{self, bail, ensure, Context, Ok}; use serde::{Deserialize, Serialize}; -use zeth_primitives::{ - b256, transactions::ethereum::EthereumTxEssence, Address, Bloom, BloomInput, B256, U256, -}; +use zeth_primitives::{b256, receipt::EvmReceipt, Address, Bloom, BloomInput, B256, U256}; use super::batcher_db::BlockInput; @@ -33,7 +31,7 @@ pub struct SystemConfig { /// Batch sender address pub batch_sender: Address, /// L2 gas limit - pub gas_limit: U256, + pub gas_limit: u64, /// Fee overhead pub l1_fee_overhead: U256, /// Fee scalar @@ -48,7 +46,7 @@ impl SystemConfig { pub fn update( &mut self, system_config_contract: &Address, - input: &BlockInput, + input: &BlockInput, ) -> anyhow::Result { let mut updated = false; @@ -63,26 +61,24 @@ impl SystemConfig { let receipts = input.receipts.as_ref().context("receipts missing")?; for receipt in receipts { - let receipt = &receipt.payload; - // skip failed transactions - if !receipt.success { + if !receipt.success() { continue; } - for log in &receipt.logs { + for log in receipt.logs() { + let (address, log) = (&log.address, &log.data); + // the log event contract address must match the system config contract // the first log event topic must match the ConfigUpdate signature - if &log.address == system_config_contract - && log.topics[0] == CONFIG_UPDATE_SIGNATURE - { + if address == system_config_contract && log.topics()[0] == CONFIG_UPDATE_SIGNATURE { updated = true; // the second topic determines the version - ensure!(log.topics[1] == CONFIG_UPDATE_VERSION, "invalid version"); + ensure!(log.topics()[1] == CONFIG_UPDATE_VERSION, "invalid version"); // the third topic determines the type of update - let update_type: u64 = U256::from_be_bytes(log.topics[2].0) + let update_type: u64 = U256::from_be_bytes(log.topics()[2].0) .try_into() .expect("invalid update type"); @@ -111,8 +107,9 @@ impl SystemConfig { 2 => { let gas_limit = log.data.get(64..96).context("invalid data")?; - self.gas_limit = - U256::try_from_be_slice(gas_limit).context("invalid gas limit")?; + self.gas_limit = U256::try_from_be_slice(gas_limit) + .map(u64::try_from) + .context("invalid gas limit")??; } // type 3: unsafeBlockSigner overwrite, as address payload 3 => { diff --git a/lib/src/output.rs b/lib/src/output.rs index 02ab5f0a..ff5e4089 100644 --- a/lib/src/output.rs +++ b/lib/src/output.rs @@ -13,13 +13,16 @@ // limitations under the License. use serde::{Deserialize, Serialize}; -use zeth_primitives::{block::Header, trie::MptNode, B256}; +use serde_with::serde_as; +use zeth_primitives::{serde_with::RlpBytes, trie::MptNode, Header, B256}; /// Output of block execution +#[serde_as] #[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] pub enum BlockBuildOutput { SUCCESS { hash: B256, + #[serde_as(as = "RlpBytes")] head: Header, state: MptNode, state_input_hash: B256, diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 534315d2..b50f99a6 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -4,7 +4,15 @@ version = "0.1.0" edition = "2021" [dependencies] -alloy-primitives = { version = "0.6.2", default-features = false, features = [ +alloy-consensus = { git = "https://github.com/Wollac/alloy.git", branch = "fix/encoding", features = [ + "k256", +] } +alloy-eips = { git = "https://github.com/Wollac/alloy.git", branch = "fix/encoding" } +alloy-network = { git = "https://github.com/Wollac/alloy.git", branch = "fix/encoding", features = [ + "k256", +] } +alloy-primitives = { version = "0.6.4", default-features = false, features = [ + "k256", "rlp", "serde", "std", @@ -14,14 +22,10 @@ alloy-rlp-derive = { version = "0.3", default-features = false } anyhow = "1.0" bytes = { version = "1.1", default-features = false } ethers-core = { version = "2.0", optional = true, features = ["optimism"] } -k256 = { version = "=0.13.3", features = [ - "std", - "ecdsa", -], default_features = false } -revm-primitives = { workspace = true, optional = true } rlp = "0.5.2" serde = { version = "1.0", features = ["derive"] } -sha2 = { version = "=0.10.6", default-features = false } +serde_with = "3.7" +sha2 = { version = "0.10.8", default-features = false } sha3 = "0.10" thiserror = "1.0" @@ -35,4 +39,3 @@ serde_json = "1.0" [features] ethers = ["dep:ethers-core"] -revm = ["dep:revm-primitives"] diff --git a/primitives/src/access_list.rs b/primitives/src/access_list.rs index c22f9111..a0cfb965 100644 --- a/primitives/src/access_list.rs +++ b/primitives/src/access_list.rs @@ -12,40 +12,4 @@ // See the License for the specific language governing permissions and // limitations under the License. -use alloy_primitives::{Address, StorageKey}; -use alloy_rlp_derive::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; -use serde::{Deserialize, Serialize}; - -/// Represents an access list as defined in EIP-2930. -/// -/// An access list is a list of addresses and storage keys that a transaction will access, -/// allowing for gas optimizations. This structure is introduced to improve the gas cost -/// calculations by making certain accesses cheaper if they are declared in this list. -#[derive( - Debug, - Clone, - PartialEq, - Eq, - Default, - Serialize, - Deserialize, - RlpEncodableWrapper, - RlpDecodableWrapper, -)] -pub struct AccessList(pub Vec); - -/// Represents an item in the [AccessList]. -/// -/// Each item specifies an Ethereum address and a set of storage keys that the transaction -/// will access. By providing this information up front, the transaction can benefit from -/// gas cost optimizations. -#[derive( - Debug, Clone, PartialEq, Eq, Default, RlpEncodable, Serialize, Deserialize, RlpDecodable, -)] -pub struct AccessListItem { - /// The Ethereum address that the transaction will access. - pub address: Address, - /// A list of storage keys associated with the given address that the transaction will - /// access. - pub storage_keys: Vec, -} +pub use alloy_eips::eip2930::{AccessList, AccessListItem}; diff --git a/primitives/src/block.rs b/primitives/src/block.rs deleted file mode 100644 index 967f4b2b..00000000 --- a/primitives/src/block.rs +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright 2023 RISC Zero, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use alloy_primitives::{b256, Address, BlockHash, BlockNumber, Bloom, Bytes, B256, B64, U256}; -use alloy_rlp_derive::RlpEncodable; -use serde::{Deserialize, Serialize}; - -use crate::{keccak::keccak, trie::EMPTY_ROOT}; - -/// Keccak-256 hash of the RLP of an empty list. -pub const EMPTY_LIST_HASH: B256 = - b256!("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347"); - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, RlpEncodable)] -#[rlp(trailing)] -pub struct Header { - /// Hash of the parent block's header. - pub parent_hash: BlockHash, - /// Unused 256-bit hash, always [EMPTY_LIST_HASH]. - pub ommers_hash: B256, - /// Address that receives the priority fees of each transaction in the block. - pub beneficiary: Address, - /// Root hash of the state trie after all transactions in the block are executed. - pub state_root: B256, - /// Root hash of the trie containing all transactions in the block. - pub transactions_root: B256, - /// Root hash of the trie containing the receipts of each transaction in the block. - pub receipts_root: B256, - /// Bloom filter for log entries in the block. - pub logs_bloom: Bloom, - /// Always set to `0` as it's unused. - pub difficulty: U256, - /// The block number in the chain. - pub number: BlockNumber, - /// Maximum amount of gas that can be used in this block. - pub gas_limit: U256, - /// Total amount of gas used by all transactions in this block. - pub gas_used: U256, - /// Value corresponding to the seconds since Epoch at this block's inception. - pub timestamp: U256, - /// Arbitrary byte array containing extra data related to the block. - pub extra_data: Bytes, - /// Hash previously used for the PoW now containing the RANDAO value. - pub mix_hash: B256, - /// Unused 64-bit hash, always zero. - pub nonce: B64, - /// Base fee paid by all transactions in the block. - pub base_fee_per_gas: U256, - /// Root hash of the trie containing all withdrawals in the block. Present after the - /// Shanghai update. - #[serde(default)] - pub withdrawals_root: Option, -} - -impl Default for Header { - /// Provides default values for a block header. - fn default() -> Self { - Header { - parent_hash: B256::ZERO, - ommers_hash: EMPTY_LIST_HASH, - beneficiary: Address::ZERO, - state_root: EMPTY_ROOT, - transactions_root: EMPTY_ROOT, - receipts_root: EMPTY_ROOT, - logs_bloom: Bloom::default(), - difficulty: U256::ZERO, - number: 0, - gas_limit: U256::ZERO, - gas_used: U256::ZERO, - timestamp: U256::ZERO, - extra_data: Bytes::new(), - mix_hash: B256::ZERO, - nonce: B64::ZERO, - base_fee_per_gas: U256::ZERO, - withdrawals_root: None, - } - } -} - -impl Header { - /// Computes the hash of the block header. - pub fn hash(&self) -> BlockHash { - keccak(alloy_rlp::encode(self)).into() - } -} - -#[cfg(test)] -mod tests { - use serde_json::json; - - use super::*; - - #[test] - fn paris() { - // first block after the Paris network upgrade - let value = json!({ - "parent_hash":"0x55b11b918355b1ef9c5db810302ebad0bf2544255b530cdce90674d5887bb286", - "ommers_hash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "beneficiary": "0xeee27662c2b8eba3cd936a23f039f3189633e4c8", - "state_root": "0x40c07091e16263270f3579385090fea02dd5f061ba6750228fcc082ff762fda7", - "transactions_root": "0x1ea1746468686159ce730c1cc49a886721244e5d1fa9a06d6d4196b6f013c82c", - "receipts_root": "0x928073fb98ce316265ea35d95ab7e2e1206cecd85242eb841dbbcc4f568fca4b", - "logs_bloom": "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "difficulty": "0x0", - "number": 15537394, - "gas_limit": "0x1c9c380", - "gas_used": "0x1c9811e", - "timestamp": "0x6322c973", - "extra_data": "0x", - "mix_hash": "0xa86c2e601b6c44eb4848f7d23d9df3113fbcac42041c49cbed5000cb4f118777", - "nonce": "0x0000000000000000", - "base_fee_per_gas": "0xb5d68e0a3" - }); - let header: Header = serde_json::from_value(value).unwrap(); - - // verify that bincode serialization works - let _: Header = bincode::deserialize(&bincode::serialize(&header).unwrap()).unwrap(); - - assert_eq!( - "0x56a9bb0302da44b8c0b3df540781424684c3af04d0b7a38d72842b762076a664", - header.hash().to_string() - ) - } - - #[test] - fn shanghai() { - // first block after the Shanghai network upgrade - let value = json!({ - "parent_hash": "0xc2558f8143d5f5acb8382b8cb2b8e2f1a10c8bdfeededad850eaca048ed85d8f", - "ommers_hash": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", - "beneficiary": "0x388c818ca8b9251b393131c08a736a67ccb19297", - "state_root": "0x7fd42f5027bc18315b3781e65f19e4c8828fd5c5fce33410f0fb4fea0b65541f", - "transactions_root": "0x6f235d618461c08943aa5c23cc751310d6177ab8a9b9a7b66ffa637d988680e6", - "receipts_root": "0xe0ac34bafdd757bcca2dea27a3fc5870dd0836998877e29361c1fc55e19416ec", - "logs_bloom": "0xb06769bc11f4d7a51a3bc4bed59367b75c32d1bd79e5970e73732ac0eed0251af0e2abc8811fc1b4c5d45a4a4eb5c5af9e73cc9a8be6ace72faadc03536d6b69fcdf80116fd89f7efbdbf38ff957e8f6ae83ccac60cf4b7c8b1c9487bebfa8ed6e42297e17172d5b678dd3f283b22f49bbf4a0565eb93d9d797b2f9a0adaff9813af53d6fffa71d5a6fb056ab73ca87659dc97c19f99839c6c3138e527161b4dfee8b1f64d42f927abc745f3ff168e8e9510e2e079f4868ba8ff94faf37c9a7947a43c1b4c931dfbef88edeb2d7ede5ceaebc85095cfbbd206646def0138683b687fa63fdf22898260d616bc714d698bc5748c7a5bff0a4a32dd797596a794a0", - "difficulty": "0x0", - "number": 17034870, - "gas_limit": "0x1c9c380", - "gas_used": "0x1c9bfe2", - "timestamp": "0x6437306f", - "extra_data": "0xd883010b05846765746888676f312e32302e32856c696e7578", - "mix_hash": "0x812ed704cc408c435c7baa6e86296c1ac654a139ae8c4a26d6460742b951d4f9", - "nonce": "0x0000000000000000", - "base_fee_per_gas": "0x42fbae6d5", - "withdrawals_root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421" - }); - let header: Header = serde_json::from_value(value).unwrap(); - - // verify that bincode serialization works - let _: Header = bincode::deserialize(&bincode::serialize(&header).unwrap()).unwrap(); - - assert_eq!( - "0xe22c56f211f03baadcc91e4eb9a24344e6848c5df4473988f893b58223f5216c", - header.hash().to_string() - ) - } -} diff --git a/primitives/src/ethers.rs b/primitives/src/ethers.rs index 8b44cf9f..97ff6358 100644 --- a/primitives/src/ethers.rs +++ b/primitives/src/ethers.rs @@ -14,29 +14,21 @@ //! Convert from Ethers types. -use alloy_primitives::{Address, Bloom, Bytes, B256, U256}; +use alloy_consensus::{Header, ReceiptEnvelope as AlloyReceiptEnvelope, SignableTransaction}; +use alloy_primitives::{Address, Bloom, Bytes, Log, Signature, B256, U256}; use anyhow::{anyhow, Context}; use ethers_core::types::{ - transaction::eip2930::{ - AccessList as EthersAccessList, AccessListItem as EthersAccessListItem, - }, - Block as EthersBlock, Bytes as EthersBytes, EIP1186ProofResponse, - Transaction as EthersTransaction, TransactionReceipt as EthersReceipt, - Withdrawal as EthersWithdrawal, H160 as EthersH160, H256 as EthersH256, U256 as EthersU256, - U64, + transaction::eip2930::AccessList as EthersAccessList, Block as EthersBlock, + Bytes as EthersBytes, EIP1186ProofResponse, Transaction as EthersTransaction, + TransactionReceipt as EthersReceipt, Withdrawal as EthersWithdrawal, H160 as EthersH160, + H256 as EthersH256, U256 as EthersU256, U64, }; use crate::{ access_list::{AccessList, AccessListItem}, - block::Header, - receipt::{Log, Receipt, ReceiptPayload, OPTIMISM_DEPOSIT_NONCE_VERSION}, + receipt::{OptimismDepositReceipt, Receipt, ReceiptEnvelope, ReceiptWithBloom}, transactions::{ - ethereum::{ - EthereumTxEssence, TransactionKind, TxEssenceEip1559, TxEssenceEip2930, TxEssenceLegacy, - }, - optimism::{OptimismTxEssence, TxEssenceOptimismDeposited}, - signature::TxSignature, - Transaction, TxEssence, + optimism::TxOptimismDeposit, TxEip1559, TxEip2930, TxEnvelope, TxLegacy, TxType, }, trie::StateAccount, withdrawal::Withdrawal, @@ -72,94 +64,105 @@ pub fn from_ethers_bytes(v: EthersBytes) -> Bytes { v.0.into() } -/// Conversion from `EthersAccessListItem` to the local [AccessListItem]. -impl From for AccessListItem { - fn from(item: EthersAccessListItem) -> Self { - AccessListItem { - address: item.address.0.into(), +/// Convert an `AccessList` type to the `EthersAccessList` type. +pub fn from_ethers_access_list(list: EthersAccessList) -> AccessList { + let items = list + .0 + .into_iter() + .map(|item| AccessListItem { + address: from_ethers_h160(item.address), storage_keys: item .storage_keys .into_iter() - .map(|key| key.0.into()) + .map(from_ethers_h256) .collect(), - } - } -} - -/// Conversion from `EthersAccessList` to the local [AccessList]. -impl From for AccessList { - fn from(list: EthersAccessList) -> Self { - AccessList(list.0.into_iter().map(|item| item.into()).collect()) - } + }) + .collect(); + AccessList(items) } -/// Convert an optional `EthersH160` to the local [TransactionKind]. -impl From> for TransactionKind { - fn from(addr: Option) -> Self { - match addr { - Some(address) => TransactionKind::Call(address.0.into()), - None => TransactionKind::Create, +fn from_ethers_transaction_type(v: Option) -> Result, anyhow::Error> { + let tx_type = match v { + Some(v) => { + let v: u8 = v + .try_into() + .map_err(|err| anyhow!("invalid transaction_type: {}", err))?; + Some(TxType::try_from(v).context("invalid transaction_type")?) } - } + None => None, + }; + Ok(tx_type) } /// Conversion from `EthersBlock` to the local [Header]. /// This conversion may fail if certain expected fields are missing. -impl TryFrom> for Header { - type Error = anyhow::Error; - - fn try_from(block: EthersBlock) -> Result { - Ok(Header { - parent_hash: from_ethers_h256(block.parent_hash), - ommers_hash: from_ethers_h256(block.uncles_hash), - beneficiary: from_ethers_h160(block.author.context("author missing")?), - state_root: from_ethers_h256(block.state_root), - transactions_root: from_ethers_h256(block.transactions_root), - receipts_root: from_ethers_h256(block.receipts_root), - logs_bloom: Bloom::from_slice( - block.logs_bloom.context("logs_bloom missing")?.as_bytes(), - ), - difficulty: from_ethers_u256(block.difficulty), - number: block.number.context("number missing")?.as_u64(), - gas_limit: from_ethers_u256(block.gas_limit), - gas_used: from_ethers_u256(block.gas_used), - timestamp: from_ethers_u256(block.timestamp), - extra_data: block.extra_data.0.into(), - mix_hash: block.mix_hash.context("mix_hash missing")?.0.into(), - nonce: block.nonce.context("nonce missing")?.0.into(), - base_fee_per_gas: from_ethers_u256( - block.base_fee_per_gas.context("base_fee_per_gas missing")?, - ), - withdrawals_root: block.withdrawals_root.map(from_ethers_h256), - }) - } +pub fn from_ethers_block(block: EthersBlock) -> Result { + Ok(Header { + parent_hash: from_ethers_h256(block.parent_hash), + ommers_hash: from_ethers_h256(block.uncles_hash), + beneficiary: from_ethers_h160(block.author.context("author missing")?), + state_root: from_ethers_h256(block.state_root), + transactions_root: from_ethers_h256(block.transactions_root), + receipts_root: from_ethers_h256(block.receipts_root), + withdrawals_root: block.withdrawals_root.map(from_ethers_h256), + logs_bloom: Bloom::from_slice(block.logs_bloom.context("logs_bloom missing")?.as_bytes()), + difficulty: from_ethers_u256(block.difficulty), + number: block.number.context("number missing")?.as_u64(), + gas_limit: block + .gas_limit + .try_into() + .map_err(|err| anyhow!("invalid gas_limit: {}", err))?, + gas_used: block + .gas_used + .try_into() + .map_err(|err| anyhow!("invalid gas_used: {}", err))?, + timestamp: block + .timestamp + .try_into() + .map_err(|err| anyhow!("invalid timestamp: {}", err))?, + mix_hash: block + .mix_hash + .map(from_ethers_h256) + .context("mix_hash missing")?, + nonce: block.nonce.context("nonce missing")?.to_low_u64_be(), + base_fee_per_gas: block + .base_fee_per_gas + .map(u64::try_from) + .transpose() + .map_err(|err| anyhow!("invalid base_fee_per_gas: {}", err))?, + blob_gas_used: block + .blob_gas_used + .map(u64::try_from) + .transpose() + .map_err(|err| anyhow!("invalid blob_gas_used: {}", err))?, + excess_blob_gas: block + .excess_blob_gas + .map(u64::try_from) + .transpose() + .map_err(|err| anyhow!("invalid excess_blob_gas: {}", err))?, + parent_beacon_block_root: block.parent_beacon_block_root.map(from_ethers_h256), + extra_data: from_ethers_bytes(block.extra_data), + }) } -/// Conversion from `EthersTransaction` to the local [Transaction]. -/// This conversion may fail if certain expected fields are missing. -impl> TryFrom for Transaction { - type Error = >::Error; - - fn try_from(value: EthersTransaction) -> Result { - let signature = TxSignature { - v: value.v.as_u64(), - r: from_ethers_u256(value.r), - s: from_ethers_u256(value.s), - }; - let essence = value.try_into()?; - - Ok(Transaction { essence, signature }) - } -} - -/// Conversion from `EthersTransaction` to the local [EthereumTxEssence]. -/// This conversion may fail if certain expected fields are missing. -impl TryFrom for EthereumTxEssence { +impl TryFrom for TxEnvelope { type Error = anyhow::Error; fn try_from(tx: EthersTransaction) -> Result { - let essence = match tx.transaction_type.map(|t| t.as_u64()) { - None | Some(0) => EthereumTxEssence::Legacy(TxEssenceLegacy { + let tx_type = from_ethers_transaction_type(tx.transaction_type)?; + + let signature = if tx_type != Some(TxType::OptimismDeposit) { + Some(Signature::from_rs_and_parity( + from_ethers_u256(tx.r), + from_ethers_u256(tx.s), + tx.v.as_u64(), + )?) + } else { + None + }; + + let tx = match tx_type { + None | Some(TxType::Legacy) => TxLegacy { chain_id: match tx.chain_id { None => None, Some(chain_id) => Some( @@ -172,13 +175,22 @@ impl TryFrom for EthereumTxEssence { .nonce .try_into() .map_err(|err| anyhow!("invalid nonce: {}", err))?, - gas_price: from_ethers_u256(tx.gas_price.context("gas_price missing")?), - gas_limit: from_ethers_u256(tx.gas), - to: tx.to.into(), + gas_price: tx + .gas_price + .context("gas_price missing")? + .try_into() + .map_err(|err| anyhow!("invalid gas_price: {}", err))?, + gas_limit: tx + .gas + .try_into() + .map_err(|err| anyhow!("invalid gas_limit: {}", err))?, + to: tx.to.map(from_ethers_h160).into(), value: from_ethers_u256(tx.value), - data: tx.input.0.into(), - }), - Some(1) => EthereumTxEssence::Eip2930(TxEssenceEip2930 { + input: tx.input.0.into(), + } + .into_signed(signature.unwrap()) + .into(), + Some(TxType::Eip2930) => TxEip2930 { chain_id: tx .chain_id .context("chain_id missing")? @@ -188,14 +200,25 @@ impl TryFrom for EthereumTxEssence { .nonce .try_into() .map_err(|err| anyhow!("invalid nonce: {}", err))?, - gas_price: from_ethers_u256(tx.gas_price.context("gas_price missing")?), - gas_limit: from_ethers_u256(tx.gas), - to: tx.to.into(), + gas_price: tx + .gas_price + .context("gas_price missing")? + .try_into() + .map_err(|err| anyhow!("invalid gas_price: {}", err))?, + gas_limit: tx + .gas + .try_into() + .map_err(|err| anyhow!("invalid gas_limit: {}", err))?, + to: tx.to.map(from_ethers_h160).into(), value: from_ethers_u256(tx.value), - access_list: tx.access_list.context("access_list missing")?.into(), - data: tx.input.0.into(), - }), - Some(2) => EthereumTxEssence::Eip1559(TxEssenceEip1559 { + access_list: from_ethers_access_list( + tx.access_list.context("access_list missing")?, + ), + input: tx.input.0.into(), + } + .into_signed(signature.unwrap()) + .into(), + Some(TxType::Eip1559) => TxEip1559 { chain_id: tx .chain_id .context("chain_id missing")? @@ -205,45 +228,46 @@ impl TryFrom for EthereumTxEssence { .nonce .try_into() .map_err(|err| anyhow!("invalid nonce: {}", err))?, - max_priority_fee_per_gas: from_ethers_u256( - tx.max_priority_fee_per_gas - .context("max_priority_fee_per_gas missing")?, - ), - max_fee_per_gas: from_ethers_u256( - tx.max_fee_per_gas.context("max_fee_per_gas missing")?, - ), - gas_limit: from_ethers_u256(tx.gas), - to: tx.to.into(), - value: from_ethers_u256(tx.value), - access_list: tx.access_list.context("access_list missing")?.into(), - data: tx.input.0.into(), - }), - _ => unreachable!(), - }; - Ok(essence) - } -} - -/// Conversion from `EthersTransaction` to the local [OptimismTxEssence]. -/// This conversion may fail if certain expected fields are missing. -impl TryFrom for OptimismTxEssence { - type Error = anyhow::Error; - - fn try_from(tx: EthersTransaction) -> Result { - let essence = match tx.transaction_type.map(|t| t.as_u64()) { - Some(0x7E) => OptimismTxEssence::OptimismDeposited(TxEssenceOptimismDeposited { - gas_limit: from_ethers_u256(tx.gas), - from: tx.from.0.into(), - to: tx.to.into(), + max_priority_fee_per_gas: tx + .max_priority_fee_per_gas + .context("max_priority_fee_per_gas missing")? + .try_into() + .map_err(|err| anyhow!("invalid max_priority_fee_per_gas: {}", err))?, + max_fee_per_gas: tx + .max_fee_per_gas + .context("max_fee_per_gas missing")? + .try_into() + .map_err(|err| anyhow!("invalid max_fee_per_gas: {}", err))?, + gas_limit: tx + .gas + .try_into() + .map_err(|err| anyhow!("invalid gas_limit: {}", err))?, + to: tx.to.map(from_ethers_h160).into(), value: from_ethers_u256(tx.value), - data: tx.input.0.into(), + access_list: from_ethers_access_list( + tx.access_list.context("access_list missing")?, + ), + input: tx.input.0.into(), + } + .into_signed(signature.unwrap()) + .into(), + Some(TxType::Eip4844) => unimplemented!("EIP-4844 not supported"), + Some(TxType::OptimismDeposit) => TxEnvelope::OptimismDeposit(TxOptimismDeposit { source_hash: from_ethers_h256(tx.source_hash), + from: tx.from.0.into(), + to: tx.to.map(from_ethers_h160).into(), mint: from_ethers_u256(tx.mint.context("mint missing")?), + value: from_ethers_u256(tx.value), + gas_limit: tx + .gas + .try_into() + .map_err(|err| anyhow!("invalid gas_limit: {}", err))?, is_system_tx: tx.is_system_tx, + input: tx.input.0.into(), }), - _ => OptimismTxEssence::Ethereum(tx.try_into()?), }; - Ok(essence) + + Ok(tx) } } @@ -265,40 +289,47 @@ impl TryFrom for Withdrawal { } } -impl TryFrom for Receipt { +impl TryFrom for ReceiptEnvelope { type Error = anyhow::Error; - fn try_from(receipt: EthersReceipt) -> Result { - Ok(Receipt { - tx_type: receipt - .transaction_type - .context("transaction_type missing")? - .as_u64() - .try_into() - .context("invalid transaction_type")?, - payload: ReceiptPayload { - success: receipt.status.context("status missing")? == U64::one(), - cumulative_gas_used: from_ethers_u256(receipt.cumulative_gas_used), - logs_bloom: Bloom::from_slice(receipt.logs_bloom.as_bytes()), - logs: receipt - .logs - .into_iter() - .map(|log| { - let address = log.address.0.into(); - let topics = log.topics.into_iter().map(from_ethers_h256).collect(); - let data = log.data.0.into(); - Log { - address, - topics, - data, - } - }) - .collect(), - deposit_nonce: receipt.deposit_nonce, - deposit_nonce_version: receipt - .deposit_nonce - .map(|_| OPTIMISM_DEPOSIT_NONCE_VERSION), - }, + fn try_from(v: EthersReceipt) -> Result { + let tx_type = from_ethers_transaction_type(v.transaction_type) + .map_err(|err| anyhow!("invalid transaction_type: {}", err))?; + + let receipt = Receipt { + success: v.status.context("status missing")? == U64::one(), + cumulative_gas_used: v.cumulative_gas_used.try_into().unwrap(), + logs: v + .logs + .into_iter() + .map(|log| { + Log::new_unchecked( + from_ethers_h160(log.address), + log.topics.into_iter().map(from_ethers_h256).collect(), + from_ethers_bytes(log.data), + ) + }) + .collect(), + }; + let receipt = ReceiptWithBloom::new(receipt, Bloom::from_slice(v.logs_bloom.as_bytes())); + + Ok(match tx_type { + None | Some(TxType::Legacy) => { + ReceiptEnvelope::Ethereum(AlloyReceiptEnvelope::Legacy(receipt)) + } + Some(TxType::Eip2930) => { + ReceiptEnvelope::Ethereum(AlloyReceiptEnvelope::Eip2930(receipt)) + } + Some(TxType::Eip1559) => { + ReceiptEnvelope::Ethereum(AlloyReceiptEnvelope::Eip1559(receipt)) + } + Some(TxType::Eip4844) => { + ReceiptEnvelope::Ethereum(AlloyReceiptEnvelope::Eip4844(receipt)) + } + Some(TxType::OptimismDeposit) => { + let receipt = OptimismDepositReceipt::new(receipt, v.deposit_nonce); + ReceiptEnvelope::OptimismDeposit(receipt) + } }) } } diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 0e244ea4..7f640a3e 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -15,7 +15,6 @@ extern crate core; pub mod access_list; -pub mod block; pub mod keccak; pub mod receipt; pub mod transactions; @@ -27,9 +26,8 @@ pub mod ethers; pub mod batch; pub mod mmr; -#[cfg(feature = "revm")] -pub mod revm; +pub use alloy_consensus::Header; pub use alloy_primitives::*; pub use alloy_rlp; @@ -54,3 +52,38 @@ where } } } + +pub mod serde_with { + use serde::{Deserialize, Deserializer, Serialize, Serializer}; + use serde_with::{DeserializeAs, SerializeAs}; + + use super::RlpBytes as _; + + pub struct RlpBytes {} + + impl SerializeAs for RlpBytes + where + T: alloy_rlp::Encodable, + { + fn serialize_as(source: &T, serializer: S) -> Result + where + S: Serializer, + { + let bytes = alloy_rlp::encode(source); + bytes.serialize(serializer) + } + } + + impl<'de, T> DeserializeAs<'de, T> for RlpBytes + where + T: alloy_rlp::Decodable, + { + fn deserialize_as(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let bytes = >::deserialize(deserializer)?; + T::decode_bytes(bytes).map_err(serde::de::Error::custom) + } + } +} diff --git a/primitives/src/receipt.rs b/primitives/src/receipt.rs index 290dcb99..5fb4ebed 100644 --- a/primitives/src/receipt.rs +++ b/primitives/src/receipt.rs @@ -12,116 +12,212 @@ // See the License for the specific language governing permissions and // limitations under the License. -use alloy_primitives::{Address, Bloom, BloomInput, Bytes, TxNumber, B256, U256}; -use alloy_rlp::Encodable; -use alloy_rlp_derive::RlpEncodable; -use serde::{Deserialize, Serialize}; +use alloy_consensus::TxReceipt; +pub use alloy_consensus::{Receipt, ReceiptEnvelope as EthReceiptEnvelope, ReceiptWithBloom}; +use alloy_eips::eip2718::{Decodable2718, Encodable2718}; +use alloy_primitives::{Bloom, Log, TxNumber}; +use alloy_rlp::{Decodable, Encodable}; +use alloy_rlp_derive::{RlpDecodable, RlpEncodable}; +use serde::{Deserialize, Deserializer, Serialize}; -/// Version of the deposit nonce field in the receipt. -pub const OPTIMISM_DEPOSIT_NONCE_VERSION: u32 = 1; - -/// Represents an Ethereum log entry. -#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable)] -pub struct Log { - /// Contract that emitted this log. - pub address: Address, - /// Topics of the log. The number of logs depend on what `LOG` opcode is used. - pub topics: Vec, - /// Arbitrary length data. - pub data: Bytes, +use crate::{ + transactions::{optimism::OPTIMISM_DEPOSITED_TX_TYPE, TxType}, + RlpBytes, +}; + +/// Represents a minimal EVM transaction receipt. +pub trait EvmReceipt: Encodable + Decodable { + /// Returns the receipt's success status. + fn success(&self) -> bool; + /// Returns the receipt's cumulative gas used. + fn cumulative_gas_used(&self) -> u64; + /// Returns the receipt's logs. + fn logs(&self) -> &[Log]; + /// Returns the receipt's logs bloom. + fn logs_bloom(&self) -> &Bloom; } -/// Payload of a [Receipt]. -#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable)] -#[rlp(trailing)] -pub struct ReceiptPayload { - /// Indicates whether the transaction was executed successfully. - pub success: bool, - /// Total gas used by the transaction. - pub cumulative_gas_used: U256, - /// A bloom filter that contains indexed information of logs for quick searching. - pub logs_bloom: Bloom, - /// Logs generated during the execution of the transaction. - pub logs: Vec, - /// Nonce of the Optimism deposit transaction persisted during execution. - #[serde(default)] - pub deposit_nonce: Option, - /// Version of the deposit nonce field in the receipt. - #[serde(default)] - pub deposit_nonce_version: Option, +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum ReceiptEnvelope { + Ethereum(EthReceiptEnvelope), + /// Receipt envelope with type flag 0x7e, containing a [OptimismDepositReceipt]. + OptimismDeposit(OptimismDepositReceipt), +} + +impl ReceiptEnvelope {} + +impl EvmReceipt for ReceiptEnvelope { + fn success(&self) -> bool { + match self { + Self::Ethereum(eth) => match eth { + EthReceiptEnvelope::Legacy(r) => r.success(), + EthReceiptEnvelope::Eip2930(r) => r.success(), + EthReceiptEnvelope::Eip1559(r) => r.success(), + EthReceiptEnvelope::Eip4844(r) => r.success(), + }, + Self::OptimismDeposit(r) => r.success, + } + } + + fn cumulative_gas_used(&self) -> u64 { + match self { + Self::Ethereum(eth) => match eth { + EthReceiptEnvelope::Legacy(r) => r.cumulative_gas_used(), + EthReceiptEnvelope::Eip2930(r) => r.cumulative_gas_used(), + EthReceiptEnvelope::Eip1559(r) => r.cumulative_gas_used(), + EthReceiptEnvelope::Eip4844(r) => r.cumulative_gas_used(), + }, + Self::OptimismDeposit(r) => r.cumulative_gas_used, + } + } + + fn logs(&self) -> &[Log] { + match self { + Self::Ethereum(eth) => match eth { + EthReceiptEnvelope::Legacy(r) => r.logs(), + EthReceiptEnvelope::Eip2930(r) => r.logs(), + EthReceiptEnvelope::Eip1559(r) => r.logs(), + EthReceiptEnvelope::Eip4844(r) => r.logs(), + }, + Self::OptimismDeposit(r) => &r.logs, + } + } + + fn logs_bloom(&self) -> &Bloom { + match self { + Self::Ethereum(eth) => match eth { + EthReceiptEnvelope::Legacy(r) => &r.bloom, + EthReceiptEnvelope::Eip2930(r) => &r.bloom, + EthReceiptEnvelope::Eip1559(r) => &r.bloom, + EthReceiptEnvelope::Eip4844(r) => &r.bloom, + }, + Self::OptimismDeposit(r) => &r.logs_bloom, + } + } } -/// Receipt containing result of transaction execution. -#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] -pub struct Receipt { - /// Type of Receipt. - pub tx_type: u8, - /// Detailed payload of the receipt. - pub payload: ReceiptPayload, +impl Serialize for ReceiptEnvelope { + fn serialize(&self, serializer: S) -> Result { + let bytes = alloy_rlp::encode(self); + bytes.serialize(serializer) + } } -impl Encodable for Receipt { - /// Encodes the receipt into the `out` buffer. +impl<'de> Deserialize<'de> for ReceiptEnvelope { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let bytes = >::deserialize(deserializer)?; + Self::decode_bytes(bytes).map_err(serde::de::Error::custom) + } +} + +/// Encodes the receipt following the EIP-2718 standard. +impl Encodable for ReceiptEnvelope { #[inline] fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { - match self.tx_type { - // For legacy transactions - 0 => self.payload.encode(out), - // For EIP-2718 typed transactions - tx_type => { - // prepend the EIP-2718 transaction type - out.put_u8(tx_type); - // append the RLP-encoded payload - self.payload.encode(out); - } - } + self.encode_2718(out); } - - /// Returns the length of the encoded receipt in bytes. #[inline] fn length(&self) -> usize { - let mut payload_length = self.payload.length(); - if self.tx_type != 0 { - payload_length += 1; - } - payload_length + self.encode_2718_len() + } +} + +/// Decodes the receipt following the EIP-2718 standard. +impl Decodable for ReceiptEnvelope { + #[inline] + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + Self::decode_2718(buf) } } -impl Receipt { - /// Constructs a new [Receipt]. - pub fn new(tx_type: u8, success: bool, cumulative_gas_used: U256, logs: Vec) -> Receipt { - let mut logs_bloom = Bloom::default(); - for log in &logs { - logs_bloom.accrue(BloomInput::Raw(log.address.as_slice())); - for topic in &log.topics { - logs_bloom.accrue(BloomInput::Raw(topic.as_slice())); +impl Encodable2718 for ReceiptEnvelope { + fn type_flag(&self) -> Option { + match self { + Self::Ethereum(eth) => eth.type_flag(), + Self::OptimismDeposit(_) => Some(TxType::OptimismDeposit as u8), + } + } + + fn encode_2718_len(&self) -> usize { + match self { + Self::Ethereum(eth) => eth.encode_2718_len(), + Self::OptimismDeposit(op) => 1 + op.length(), + } + } + + fn encode_2718(&self, out: &mut dyn bytes::BufMut) { + match self { + Self::Ethereum(eth) => Encodable2718::encode_2718(eth, out), + Self::OptimismDeposit(op) => { + out.put_u8(OPTIMISM_DEPOSITED_TX_TYPE); + op.encode(out); } } + } +} - Receipt { - tx_type, - payload: ReceiptPayload { - success, - cumulative_gas_used, - logs_bloom, - logs, - deposit_nonce: None, - deposit_nonce_version: None, - }, +impl Decodable2718 for ReceiptEnvelope { + fn typed_decode(ty: u8, buf: &mut &[u8]) -> alloy_rlp::Result { + match ty { + OPTIMISM_DEPOSITED_TX_TYPE => Ok(Self::OptimismDeposit(Decodable::decode(buf)?)), + _ => Ok(ReceiptEnvelope::Ethereum(EthReceiptEnvelope::typed_decode( + ty, buf, + )?)), } } - /// Adds a deposit nonce to the receipt. - pub fn with_deposit_nonce(mut self, deposit_nonce: TxNumber) -> Self { - self.payload.deposit_nonce = Some(deposit_nonce); - self.payload.deposit_nonce_version = Some(OPTIMISM_DEPOSIT_NONCE_VERSION); - self + + fn fallback_decode(buf: &mut &[u8]) -> alloy_rlp::Result { + Ok(ReceiptEnvelope::Ethereum( + EthReceiptEnvelope::fallback_decode(buf)?, + )) + } +} + +/// Version of the deposit nonce field in the receipt. +const OPTIMISM_DEPOSIT_NONCE_VERSION: usize = 1; + +/// Receipt containing result of an Optimism Deposit transaction execution. +/// The Deposit transaction receipt type is equal to a regular receipt, but extended with +/// an optional `depositNonce` field. +#[derive(Clone, Debug, PartialEq, Eq, Default, RlpEncodable, RlpDecodable)] +#[rlp(trailing)] +pub struct OptimismDepositReceipt { + /// Indicates whether the transaction was executed successfully. + pub success: bool, + /// Total gas used by the transaction. + pub cumulative_gas_used: u64, + /// A bloom filter that contains indexed information of logs for quick searching. + pub logs_bloom: Bloom, + /// Logs generated during the execution of the transaction. + pub logs: Vec, + /// Nonce of the Optimism deposit transaction persisted during execution. + pub deposit_nonce: Option, + /// Version of the deposit nonce field in the receipt. + pub deposit_nonce_version: Option, +} + +impl OptimismDepositReceipt { + /// Constructs a new [OptimismDepositReceipt]. + /// With Canyon, the deposit nonce must be supplied. + pub fn new(receipt: ReceiptWithBloom, deposit_nonce: Option) -> Self { + Self { + success: receipt.receipt.success, + cumulative_gas_used: receipt.receipt.cumulative_gas_used, + logs_bloom: receipt.bloom, + logs: receipt.receipt.logs, + deposit_nonce, + deposit_nonce_version: deposit_nonce.map(|_| OPTIMISM_DEPOSIT_NONCE_VERSION), + } } } // test vectors from https://github.com/ethereum/go-ethereum/blob/c40ab6af72ce282020d03c33e8273ea9b03d58f6/core/types/receipt_test.go #[cfg(test)] mod tests { + use alloy_consensus::Receipt; use hex_literal::hex; use serde_json::json; @@ -130,11 +226,10 @@ mod tests { #[test] fn legacy() { let expected = hex!("f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); - let receipt = Receipt::new( - 0, - false, - U256::from(1), - serde_json::from_value(json!([ + let receipt = Receipt { + success: false, + cumulative_gas_used: 1, + logs: serde_json::from_value(json!([ { "address": "0x0000000000000000000000000000000000000011", "topics": [ @@ -153,21 +248,18 @@ mod tests { } ])) .unwrap(), - ); - let mut data = vec![]; - receipt.encode(&mut data); - - assert_eq!(data, expected); + }; + let envelop = ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Legacy(receipt.into())); + assert_eq!(envelop.encoded_2718(), expected); } #[test] fn eip2930() { let expected = hex!("01f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); - let receipt = Receipt::new( - 1, - false, - U256::from(1), - serde_json::from_value(json!([ + let receipt = Receipt { + success: false, + cumulative_gas_used: 1, + logs: serde_json::from_value(json!([ { "address": "0x0000000000000000000000000000000000000011", "topics": [ @@ -186,21 +278,18 @@ mod tests { } ])) .unwrap(), - ); - let mut data = vec![]; - receipt.encode(&mut data); - - assert_eq!(data, expected); + }; + let envelop = ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Eip2930(receipt.into())); + assert_eq!(envelop.encoded_2718(), expected); } #[test] fn eip1559() { let expected = hex!("02f901c58001b9010000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000000000000000000010000080000000000000000000004000000000000000000000000000040000000000000000000000000000800000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000f8bef85d940000000000000000000000000000000000000011f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100fff85d940000000000000000000000000000000000000111f842a0000000000000000000000000000000000000000000000000000000000000deada0000000000000000000000000000000000000000000000000000000000000beef830100ff"); - let receipt = Receipt::new( - 2, - false, - U256::from(1), - serde_json::from_value(json!([ + let receipt = Receipt { + success: false, + cumulative_gas_used: 1, + logs: serde_json::from_value(json!([ { "address": "0x0000000000000000000000000000000000000011", "topics": [ @@ -219,10 +308,8 @@ mod tests { } ])) .unwrap(), - ); - let mut data = vec![]; - receipt.encode(&mut data); - - assert_eq!(data, expected); + }; + let envelop = ReceiptEnvelope::Ethereum(EthReceiptEnvelope::Eip1559(receipt.into())); + assert_eq!(envelop.encoded_2718(), expected); } } diff --git a/primitives/src/revm.rs b/primitives/src/revm.rs deleted file mode 100644 index 726d2438..00000000 --- a/primitives/src/revm.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2024 RISC Zero, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//! Convert to revm types. - -use alloy_primitives::{Address, U256}; -use revm_primitives::Log as RevmLog; - -use crate::{ - access_list::{AccessList, AccessListItem}, - receipt::Log, -}; - -/// Provides a conversion from [AccessListItem] to a tuple of `Address` and a vector of -/// `U256`. -impl From for (Address, Vec) { - fn from(item: AccessListItem) -> (Address, Vec) { - ( - item.address, - item.storage_keys - .into_iter() - .map(|item| item.into()) - .collect(), - ) - } -} - -/// Provides a conversion from [AccessList] to a vector of tuples containing `Address` and -/// a vector of `U256`. -impl From for Vec<(Address, Vec)> { - fn from(list: AccessList) -> Vec<(Address, Vec)> { - list.0.into_iter().map(|item| item.into()).collect() - } -} - -/// Provides a conversion from `RevmLog` to the local [Log]. -impl From for Log { - fn from(log: RevmLog) -> Self { - Log { - address: log.address, - topics: log.data.topics().to_vec(), - data: log.data.data, - } - } -} diff --git a/primitives/src/transactions/ethereum.rs b/primitives/src/transactions/ethereum.rs deleted file mode 100644 index 42a0f368..00000000 --- a/primitives/src/transactions/ethereum.rs +++ /dev/null @@ -1,844 +0,0 @@ -// Copyright 2024 RISC Zero, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use alloy_primitives::{Address, Bytes, ChainId, TxNumber, B256, U256}; -use alloy_rlp::{Decodable, Encodable, EMPTY_STRING_CODE}; -use alloy_rlp_derive::{RlpDecodable, RlpEncodable}; -use anyhow::Context; -use bytes::Buf; -use k256::{ - ecdsa::{RecoveryId, Signature as K256Signature, VerifyingKey as K256VerifyingKey}, - elliptic_curve::sec1::ToEncodedPoint, - PublicKey as K256PublicKey, -}; -use serde::{Deserialize, Serialize}; - -use super::signature::TxSignature; -use crate::{ - access_list::AccessList, - keccak::keccak, - transactions::{SignedDecodable, TxEssence}, -}; - -/// Represents a legacy Ethereum transaction as detailed in [EIP-155](https://eips.ethereum.org/EIPS/eip-155). -/// -/// The `TxEssenceLegacy` struct encapsulates the core components of a traditional -/// Ethereum transaction prior to the introduction of more recent transaction types. It -/// adheres to the specifications set out in EIP-155. -#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] -pub struct TxEssenceLegacy { - /// The network's chain ID introduced in EIP-155 to prevent replay attacks across - /// different chains. - pub chain_id: Option, - /// A numeric value representing the total number of transactions previously sent by - /// the sender. - pub nonce: TxNumber, - /// The price, in Wei, that the sender is willing to pay per unit of gas for the - /// transaction's execution. - pub gas_price: U256, - /// The maximum amount of gas allocated for the transaction's execution. - pub gas_limit: U256, - /// The 160-bit address of the intended recipient for a message call or - /// [TransactionKind::Create] for contract creation. - pub to: TransactionKind, - /// The amount, in Wei, to be transferred to the recipient of the message call. - pub value: U256, - /// The transaction's payload, represented as a variable-length byte array. - pub data: Bytes, -} - -#[derive( - Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable, -)] -struct TxEssenceLegacyTxSignature { - pub nonce: TxNumber, - pub gas_price: U256, - pub gas_limit: U256, - pub to: TransactionKind, - pub value: U256, - pub data: Bytes, - pub v: u64, - pub r: U256, - pub s: U256, -} - -impl SignedDecodable for TxEssenceLegacy { - fn decode_signed(buf: &mut &[u8]) -> alloy_rlp::Result<(Self, TxSignature)> { - let signed_essence = TxEssenceLegacyTxSignature::decode(buf)?; - let signature = TxSignature { - v: signed_essence.v, - r: signed_essence.r, - s: signed_essence.s, - }; - Ok(( - Self { - // with EIP-155, the chain_id is derived from the signature - chain_id: signature.chain_id(), - nonce: signed_essence.nonce, - gas_price: signed_essence.gas_price, - gas_limit: signed_essence.gas_limit, - to: signed_essence.to, - value: signed_essence.value, - data: signed_essence.data, - }, - signature, - )) - } -} - -impl TxEssenceLegacy { - /// Computes the length of the RLP-encoded payload in bytes. - /// - /// This method calculates the combined length of all the individual fields - /// of the transaction when they are RLP-encoded. - pub fn payload_length(&self) -> usize { - self.nonce.length() - + self.gas_price.length() - + self.gas_limit.length() - + self.to.length() - + self.value.length() - + self.data.length() - } - - /// Encodes the transaction essence into the provided `out` buffer for the purpose of - /// signing. - /// - /// According to EIP-155, if `chain_id` is present, `(chain_id, 0, 0)` must be - /// appended to the regular RLP encoding when computing the hash of a transaction for - /// the purposes of signing. - pub fn signing_encode(&self, out: &mut dyn alloy_rlp::BufMut) { - let mut payload_length = self.payload_length(); - // append chain ID according to EIP-155 if present - if let Some(chain_id) = self.chain_id { - payload_length += chain_id.length() + 1 + 1; - } - alloy_rlp::Header { - list: true, - payload_length, - } - .encode(out); - self.nonce.encode(out); - self.gas_price.encode(out); - self.gas_limit.encode(out); - self.to.encode(out); - self.value.encode(out); - self.data.encode(out); - if let Some(chain_id) = self.chain_id { - chain_id.encode(out); - out.put_u8(alloy_rlp::EMPTY_STRING_CODE); - out.put_u8(alloy_rlp::EMPTY_STRING_CODE); - } - } - - /// Computes the length of the RLP-encoded transaction essence in bytes, specifically - /// for signing. - /// - /// This method calculates the total length of the transaction when it is RLP-encoded, - /// including any additional bytes required for the encoding format. - pub fn signing_length(&self) -> usize { - let mut payload_length = self.payload_length(); - // append chain ID according to EIP-155 if present - if let Some(chain_id) = self.chain_id { - payload_length += chain_id.length() + 1 + 1; - } - payload_length + alloy_rlp::length_of_length(payload_length) - } -} - -// Implement the Encodable trait for `TxEssenceLegacy`. -// Ensures that the `chain_id` is always ignored during the RLP encoding process. -impl Encodable for TxEssenceLegacy { - /// Encodes the [TxEssenceLegacy] instance into the provided `out` buffer. - /// - /// This method follows the RLP encoding scheme, but intentionally omits the - /// `chain_id` to ensure compatibility with legacy transactions. - #[inline] - fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { - alloy_rlp::Header { - list: true, - payload_length: self.payload_length(), - } - .encode(out); - self.nonce.encode(out); - self.gas_price.encode(out); - self.gas_limit.encode(out); - self.to.encode(out); - self.value.encode(out); - self.data.encode(out); - } - - /// Computes the length of the RLP-encoded [TxEssenceLegacy] instance in bytes. - /// - /// This method calculates the total length of the transaction when it is RLP-encoded, - /// excluding the `chain_id`. - #[inline] - fn length(&self) -> usize { - let payload_length = self.payload_length(); - payload_length + alloy_rlp::length_of_length(payload_length) - } -} - -/// Represents an Ethereum transaction with an access list, as detailed in [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930). -/// -/// The `TxEssenceEip2930` struct encapsulates the core components of an Ethereum -/// transaction that includes an access list. Access lists are a feature introduced in -/// EIP-2930 to specify a list of addresses and storage keys that the transaction will -/// access, allowing for more predictable gas costs. -#[derive( - Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable, -)] -pub struct TxEssenceEip2930 { - /// The network's chain ID, ensuring the transaction is valid on the intended chain. - pub chain_id: ChainId, - /// A numeric value representing the total number of transactions previously sent by - /// the sender. - pub nonce: TxNumber, - /// The price, in Wei, that the sender is willing to pay per unit of gas for the - /// transaction's execution. - pub gas_price: U256, - /// The maximum amount of gas allocated for the transaction's execution. - pub gas_limit: U256, - /// The 160-bit address of the intended recipient for a message call. For contract - /// creation transactions, this is null. - pub to: TransactionKind, - /// The amount, in Wei, to be transferred to the recipient of the message call. - pub value: U256, - /// The transaction's payload, represented as a variable-length byte array. - pub data: Bytes, - /// A list of addresses and storage keys that the transaction will access, helping in - /// gas optimization. - pub access_list: AccessList, -} - -#[derive( - Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable, -)] -struct TxEssenceEip2930TxSignature { - pub chain_id: ChainId, - pub nonce: TxNumber, - pub gas_price: U256, - pub gas_limit: U256, - pub to: TransactionKind, - pub value: U256, - pub data: Bytes, - pub access_list: AccessList, - pub v: u64, - pub r: U256, - pub s: U256, -} - -impl SignedDecodable for TxEssenceEip2930 { - fn decode_signed(buf: &mut &[u8]) -> alloy_rlp::Result<(Self, TxSignature)> { - let signed_essence = TxEssenceEip2930TxSignature::decode(buf)?; - Ok(( - Self { - chain_id: signed_essence.chain_id, - nonce: signed_essence.nonce, - gas_price: signed_essence.gas_price, - gas_limit: signed_essence.gas_limit, - to: signed_essence.to, - value: signed_essence.value, - data: signed_essence.data, - access_list: signed_essence.access_list, - }, - TxSignature { - v: signed_essence.v, - r: signed_essence.r, - s: signed_essence.s, - }, - )) - } -} - -/// Represents an Ethereum transaction with a priority fee, as detailed in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). -/// -/// The `TxEssenceEip1559` struct encapsulates the core components of an Ethereum -/// transaction that incorporates the priority fee mechanism introduced in EIP-1559. This -/// mechanism aims to improve the predictability of gas fees and enhance the overall user -/// experience. -#[derive( - Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable, -)] -pub struct TxEssenceEip1559 { - /// The network's chain ID, ensuring the transaction is valid on the intended chain, - /// as introduced in EIP-155. - pub chain_id: ChainId, - /// A numeric value representing the total number of transactions previously sent by - /// the sender. - pub nonce: TxNumber, - /// The maximum priority fee per unit of gas that the sender is willing to pay to the - /// miner. - pub max_priority_fee_per_gas: U256, - /// The combined maximum fee (base + priority) per unit of gas that the sender is - /// willing to pay for the transaction's execution. - pub max_fee_per_gas: U256, - /// The maximum amount of gas allocated for the transaction's execution. - pub gas_limit: U256, - /// The 160-bit address of the intended recipient for a message call. For contract - /// creation transactions, this is null. - pub to: TransactionKind, - /// The amount, in Wei, to be transferred to the recipient of the message call. - pub value: U256, - /// The transaction's payload, represented as a variable-length byte array. - pub data: Bytes, - /// A list of addresses and storage keys that the transaction will access, aiding in - /// gas optimization. - pub access_list: AccessList, -} - -#[derive( - Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable, -)] -struct TxEssenceEip1559TxSignature { - pub chain_id: ChainId, - pub nonce: TxNumber, - pub max_priority_fee_per_gas: U256, - pub max_fee_per_gas: U256, - pub gas_limit: U256, - pub to: TransactionKind, - pub value: U256, - pub data: Bytes, - pub access_list: AccessList, - pub v: u64, - pub r: U256, - pub s: U256, -} - -impl SignedDecodable for TxEssenceEip1559 { - fn decode_signed(buf: &mut &[u8]) -> alloy_rlp::Result<(Self, TxSignature)> { - let signed_essence = TxEssenceEip1559TxSignature::decode(buf)?; - Ok(( - Self { - chain_id: signed_essence.chain_id, - nonce: signed_essence.nonce, - max_priority_fee_per_gas: signed_essence.max_priority_fee_per_gas, - max_fee_per_gas: signed_essence.max_fee_per_gas, - gas_limit: signed_essence.gas_limit, - to: signed_essence.to, - value: signed_essence.value, - data: signed_essence.data, - access_list: signed_essence.access_list, - }, - TxSignature { - v: signed_essence.v, - r: signed_essence.r, - s: signed_essence.s, - }, - )) - } -} - -/// Represents the type of an Ethereum transaction: either a contract creation or a call -/// to an existing contract. -/// -/// This enum is used to distinguish between the two primary types of Ethereum -/// transactions. It avoids using an [Option] for this purpose because options get RLP -/// encoded into lists. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)] -pub enum TransactionKind { - /// Indicates that the transaction is for creating a new contract on the Ethereum - /// network. - #[default] - Create, - /// Indicates that the transaction is a call to an existing contract, identified by - /// its 160-bit address. - Call(Address), -} - -/// Provides a conversion from [TransactionKind] to `Option
`. -/// -/// This implementation allows for a straightforward extraction of the Ethereum address -/// from a [TransactionKind]. If the transaction kind is a `Call`, the address is wrapped -/// in a `Some`. If it's a `Create`, the result is `None`. -impl From for Option
{ - /// Converts a [TransactionKind] into an `Option
`. - /// - /// - If the transaction kind is `Create`, this returns `None`. - /// - If the transaction kind is `Call`, this returns the address wrapped in a `Some`. - fn from(value: TransactionKind) -> Self { - match value { - TransactionKind::Create => None, - TransactionKind::Call(addr) => Some(addr), - } - } -} - -/// Provides RLP encoding functionality for the [TransactionKind] enum. -/// -/// This implementation ensures that each variant of the [TransactionKind] enum can be -/// RLP-encoded. -/// - The `Call` variant is encoded as the address it contains. -/// - The `Create` variant is encoded as an empty string. -impl Encodable for TransactionKind { - /// Encodes the [TransactionKind] enum variant into the provided `out` buffer. - /// - /// If the transaction kind is `Call`, the Ethereum address is encoded directly. - /// If the transaction kind is `Create`, an empty string code is added to the buffer. - #[inline] - fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { - match self { - TransactionKind::Call(addr) => addr.encode(out), - TransactionKind::Create => out.put_u8(EMPTY_STRING_CODE), - } - } - - /// Computes the length of the RLP-encoded [TransactionKind] enum variant in bytes. - /// - /// If the transaction kind is `Call`, this returns the length of the Ethereum - /// address. If the transaction kind is `Create`, this returns 1 (length of the - /// empty string code). - #[inline] - fn length(&self) -> usize { - match self { - TransactionKind::Call(addr) => addr.length(), - TransactionKind::Create => 1, - } - } -} - -impl Decodable for TransactionKind { - fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { - match buf.first().copied() { - Some(EMPTY_STRING_CODE) => { - buf.advance(1); - Ok(TransactionKind::Create) - } - _ => Address::decode(buf).map(TransactionKind::Call), - } - } -} - -/// Represents the core essence of an Ethereum transaction, specifically the portion that -/// gets signed. -/// -/// The [EthereumTxEssence] enum provides a way to handle different types of Ethereum -/// transactions. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum EthereumTxEssence { - /// Represents a legacy Ethereum transaction, which follows the original transaction - /// format. - Legacy(TxEssenceLegacy), - /// Represents an Ethereum transaction that includes an access list, as introduced in [EIP-2930](https://eips.ethereum.org/EIPS/eip-2930). - /// Access lists specify a list of addresses and storage keys that the transaction - /// will access, allowing for more predictable gas costs. - Eip2930(TxEssenceEip2930), - /// Represents an Ethereum transaction that incorporates a priority fee mechanism, as detailed in [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559). - /// This mechanism aims to improve the predictability of gas fees and enhances the - /// overall user experience. - Eip1559(TxEssenceEip1559), -} - -impl Encodable for EthereumTxEssence { - /// Encodes the [EthereumTxEssence] enum variant into the provided `out` buffer. - /// - /// Depending on the variant of the [EthereumTxEssence] enum, this method will - /// delegate the encoding process to the appropriate transaction type's encoding - /// method. - #[inline] - fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { - match self { - EthereumTxEssence::Legacy(tx) => tx.encode(out), - EthereumTxEssence::Eip2930(tx) => tx.encode(out), - EthereumTxEssence::Eip1559(tx) => tx.encode(out), - } - } - - /// Computes the length of the RLP-encoded [EthereumTxEssence] enum variant in bytes. - /// - /// Depending on the variant of the [EthereumTxEssence] enum, this method will - /// delegate the length computation to the appropriate transaction type's length - /// method. - #[inline] - fn length(&self) -> usize { - match self { - EthereumTxEssence::Legacy(tx) => tx.length(), - EthereumTxEssence::Eip2930(tx) => tx.length(), - EthereumTxEssence::Eip1559(tx) => tx.length(), - } - } -} - -impl SignedDecodable for EthereumTxEssence { - fn decode_signed(buf: &mut &[u8]) -> alloy_rlp::Result<(Self, TxSignature)> { - match buf.first().copied() { - // check the EIP-2718 transaction type for non-legacy transactions - Some(value) if value <= 0x7f => { - buf.advance(1); - // typed tx - match value { - 0x01 => TxEssenceEip2930::decode_signed(buf) - .map(|(e, s)| (EthereumTxEssence::Eip2930(e), s)), - 0x02 => TxEssenceEip1559::decode_signed(buf) - .map(|(e, s)| (EthereumTxEssence::Eip1559(e), s)), - _ => Err(alloy_rlp::Error::Custom("Unsupported transaction type")), - } - } - // Legacy transactions - Some(_) => { - TxEssenceLegacy::decode_signed(buf).map(|(e, s)| (EthereumTxEssence::Legacy(e), s)) - } - None => Err(alloy_rlp::Error::InputTooShort), - } - } -} - -impl EthereumTxEssence { - /// Computes the signing hash for the transaction essence. - /// - /// This method calculates the Keccak hash of the data that needs to be signed - /// for the transaction, ensuring the integrity and authenticity of the transaction. - pub(crate) fn signing_hash(&self) -> B256 { - keccak(self.signing_data()).into() - } - - /// Retrieves the data that should be signed for the transaction essence. - /// - /// Depending on the variant of the [EthereumTxEssence] enum, this method prepares the - /// appropriate data for signing. For EIP-2930 and EIP-1559 transactions, a specific - /// prefix byte is added before the transaction data. - fn signing_data(&self) -> Vec { - match self { - EthereumTxEssence::Legacy(tx) => { - let mut buf = Vec::with_capacity(tx.signing_length()); - tx.signing_encode(&mut buf); - buf - } - EthereumTxEssence::Eip2930(tx) => { - let mut buf = Vec::with_capacity(tx.length() + 1); - buf.push(0x01); - tx.encode(&mut buf); - buf - } - EthereumTxEssence::Eip1559(tx) => { - let mut buf = Vec::with_capacity(tx.length() + 1); - buf.push(0x02); - tx.encode(&mut buf); - buf - } - } - } - - /// Returns the parity of the y-value of the curve point for which `signature.r` is - /// the x-value. This is encoded in the `v` field of the signature. - /// - /// It returns `None` if the parity cannot be determined. - fn is_y_odd(&self, signature: &TxSignature) -> Option { - match self { - EthereumTxEssence::Legacy(TxEssenceLegacy { chain_id: None, .. }) => { - checked_bool(signature.v - 27) - } - EthereumTxEssence::Legacy(TxEssenceLegacy { - chain_id: Some(chain_id), - .. - }) => checked_bool(signature.v - 35 - 2 * chain_id), - _ => checked_bool(signature.v), - } - } -} - -/// Converts a given value into a boolean based on its parity. -fn checked_bool(v: u64) -> Option { - match v { - 0 => Some(false), - 1 => Some(true), - _ => None, - } -} - -impl TxEssence for EthereumTxEssence { - /// Returns the EIP-2718 transaction type or `0x00` for Legacy transactions. - fn tx_type(&self) -> u8 { - match self { - EthereumTxEssence::Legacy(_) => 0x00, - EthereumTxEssence::Eip2930(_) => 0x01, - EthereumTxEssence::Eip1559(_) => 0x02, - } - } - /// Returns the gas limit set for the transaction. - fn gas_limit(&self) -> U256 { - match self { - EthereumTxEssence::Legacy(tx) => tx.gas_limit, - EthereumTxEssence::Eip2930(tx) => tx.gas_limit, - EthereumTxEssence::Eip1559(tx) => tx.gas_limit, - } - } - /// Returns the recipient address of the transaction, if available. - fn to(&self) -> Option
{ - match self { - EthereumTxEssence::Legacy(tx) => tx.to.into(), - EthereumTxEssence::Eip2930(tx) => tx.to.into(), - EthereumTxEssence::Eip1559(tx) => tx.to.into(), - } - } - /// Recovers the Ethereum address of the sender from the transaction's signature. - fn recover_from(&self, signature: &TxSignature) -> anyhow::Result
{ - let is_y_odd = self.is_y_odd(signature).context("v invalid")?; - let signature = - K256Signature::from_scalars(signature.r.to_be_bytes(), signature.s.to_be_bytes()) - .context("r, s invalid")?; - - let verify_key = K256VerifyingKey::recover_from_prehash( - self.signing_hash().as_slice(), - &signature, - RecoveryId::new(is_y_odd, false), - ) - .context("invalid signature")?; - - let public_key = K256PublicKey::from(&verify_key); - let public_key = public_key.to_encoded_point(false); - let public_key = public_key.as_bytes(); - debug_assert_eq!(public_key[0], 0x04); - let hash = keccak(&public_key[1..]); - - Ok(Address::from_slice(&hash[12..])) - } - /// Returns the length of the RLP-encoding payload in bytes. - fn payload_length(&self) -> usize { - match self { - EthereumTxEssence::Legacy(tx) => tx.payload_length(), - EthereumTxEssence::Eip2930(tx) => tx._alloy_rlp_payload_length(), - EthereumTxEssence::Eip1559(tx) => tx._alloy_rlp_payload_length(), - } - } - /// Returns a reference to the transaction's call data - fn data(&self) -> &Bytes { - match self { - EthereumTxEssence::Legacy(tx) => &tx.data, - EthereumTxEssence::Eip2930(tx) => &tx.data, - EthereumTxEssence::Eip1559(tx) => &tx.data, - } - } -} - -#[cfg(test)] -mod tests { - use alloy_primitives::{address, b256}; - use serde_json::json; - - use super::*; - use crate::{ - transactions::{EthereumTransaction, Transaction}, - RlpBytes, - }; - - #[test] - fn legacy() { - // Tx: 0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060 - let tx = json!({ - "Legacy": { - "nonce": 0, - "gas_price": "0x2d79883d2000", - "gas_limit": "0x5208", - "to": { "Call": "0x5df9b87991262f6ba471f09758cde1c0fc1de734" }, - "value": "0x7a69", - "data": "0x" - } - }); - let essence: EthereumTxEssence = serde_json::from_value(tx).unwrap(); - - let signature: TxSignature = serde_json::from_value(json!({ - "v": 28, - "r": "0x88ff6cf0fefd94db46111149ae4bfc179e9b94721fffd821d38d16464b3f71d0", - "s": "0x45e0aff800961cfce805daef7016b9b675c137a6a41a548f7b60a3484c06a33a" - })) - .unwrap(); - let transaction = EthereumTransaction { essence, signature }; - - // verify the RLP roundtrip - let decoded = Transaction::decode_bytes(alloy_rlp::encode(&transaction)).unwrap(); - assert_eq!(transaction, decoded); - - // verify that bincode serialization works - let _: EthereumTransaction = - bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); - - assert_eq!( - transaction.hash(), - b256!("5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060") - ); - let recovered = transaction.recover_from().unwrap(); - assert_eq!( - recovered, - address!("a1e4380a3b1f749673e270229993ee55f35663b4") - ); - } - - #[test] - fn eip155() { - // Tx: 0x4540eb9c46b1654c26353ac3c65e56451f711926982ce1b02f15c50e7459caf7 - let tx = json!({ - "Legacy": { - "nonce": 537760, - "gas_price": "0x03c49bfa04", - "gas_limit": "0x019a28", - "to": { "Call": "0xf0ee707731d1be239f9f482e1b2ea5384c0c426f" }, - "value": "0x06df842eaa9fb800", - "data": "0x", - "chain_id": 1 - } - }); - let essence: EthereumTxEssence = serde_json::from_value(tx).unwrap(); - - let signature: TxSignature = serde_json::from_value(json!({ - "v": 38, - "r": "0xcadd790a37b78e5613c8cf44dc3002e3d7f06a5325d045963c708efe3f9fdf7a", - "s": "0x1f63adb9a2d5e020c6aa0ff64695e25d7d9a780ed8471abe716d2dc0bf7d4259" - })) - .unwrap(); - let transaction = EthereumTransaction { essence, signature }; - - // verify the RLP roundtrip - let decoded = Transaction::decode_bytes(alloy_rlp::encode(&transaction)).unwrap(); - assert_eq!(transaction, decoded); - - // verify that bincode serialization works - let _: EthereumTransaction = - bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); - - assert_eq!( - transaction.hash(), - b256!("4540eb9c46b1654c26353ac3c65e56451f711926982ce1b02f15c50e7459caf7") - ); - let recovered = transaction.recover_from().unwrap(); - assert_eq!( - recovered, - address!("974caa59e49682cda0ad2bbe82983419a2ecc400") - ); - } - - #[test] - fn eip2930() { - // Tx: 0xbe4ef1a2244e99b1ef518aec10763b61360be22e3b649dcdf804103719b1faef - let tx = json!({ - "Eip2930": { - "chain_id": 1, - "nonce": 93847, - "gas_price": "0xf46a5a9d8", - "gas_limit": "0x21670", - "to": { "Call": "0xc11ce44147c9f6149fbe54adb0588523c38718d7" }, - "value": "0x10d1471", - "data": "0x050000000002b8809aef26206090eafd7d5688615d48197d1c5ce09be6c30a33be4c861dee44d13f6dd33c2e8c5cad7e2725f88a8f0000000002d67ca5eb0e5fb6", - "access_list": [ - { - "address": "0xd6e64961ba13ba42858ad8a74ed9a9b051a4957d", - "storage_keys": [ - "0x0000000000000000000000000000000000000000000000000000000000000008", - "0x0b4b38935f88a7bddbe6be76893de2a04640a55799d6160729a82349aff1ffae", - "0xc59ee2ee2ba599569b2b1f06989dadbec5ee157c8facfe64f36a3e33c2b9d1bf" - ] - }, - { - "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", - "storage_keys": [ - "0x7635825e4f8dfeb20367f8742c8aac958a66caa001d982b3a864dcc84167be80", - "0x42555691810bdf8f236c31de88d2cc9407a8ff86cd230ba3b7029254168df92a", - "0x29ece5a5f4f3e7751868475502ab752b5f5fa09010960779bf7204deb72f5dde" - ] - }, - { - "address": "0x4c861dee44d13f6dd33c2e8c5cad7e2725f88a8f", - "storage_keys": [ - "0x000000000000000000000000000000000000000000000000000000000000000c", - "0x0000000000000000000000000000000000000000000000000000000000000008", - "0x0000000000000000000000000000000000000000000000000000000000000006", - "0x0000000000000000000000000000000000000000000000000000000000000007" - ] - }, - { - "address": "0x90eafd7d5688615d48197d1c5ce09be6c30a33be", - "storage_keys": [ - "0x0000000000000000000000000000000000000000000000000000000000000001", - "0x9c04773acff4c5c42718bd0120c72761f458e43068a3961eb935577d1ed4effb", - "0x0000000000000000000000000000000000000000000000000000000000000008", - "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x0000000000000000000000000000000000000000000000000000000000000004" - ] - } - ] - } - }); - let essence: EthereumTxEssence = serde_json::from_value(tx).unwrap(); - - let signature: TxSignature = serde_json::from_value(json!({ - "v": 1, - "r": "0xf86aa2dfde99b0d6a41741e96cfcdee0c6271febd63be4056911db19ae347e66", - "s": "0x601deefbc4835cb15aa1af84af6436fc692dea3428d53e7ff3d34a314cefe7fc" - })) - .unwrap(); - let transaction = EthereumTransaction { essence, signature }; - - // verify the RLP roundtrip - let decoded = Transaction::decode_bytes(alloy_rlp::encode(&transaction)).unwrap(); - assert_eq!(transaction, decoded); - - // verify that bincode serialization works - let _: EthereumTransaction = - bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); - - assert_eq!( - transaction.hash(), - b256!("be4ef1a2244e99b1ef518aec10763b61360be22e3b649dcdf804103719b1faef") - ); - let recovered = transaction.recover_from().unwrap(); - assert_eq!( - recovered, - address!("79b7a69d90c82e014bf0315e164208119b510fa0") - ); - } - - #[test] - fn eip1559() { - // Tx: 0x2bcdc03343ca9c050f8dfd3c87f32db718c762ae889f56762d8d8bdb7c5d69ff - let tx = json!({ - "Eip1559": { - "chain_id": 1, - "nonce": 32, - "max_priority_fee_per_gas": "0x3b9aca00", - "max_fee_per_gas": "0x89d5f3200", - "gas_limit": "0x5b04", - "to": { "Call": "0xa9d1e08c7793af67e9d92fe308d5697fb81d3e43" }, - "value": "0x1dd1f234f68cde2", - "data": "0x", - "access_list": [] - } - }); - let essence: EthereumTxEssence = serde_json::from_value(tx).unwrap(); - - let signature: TxSignature = serde_json::from_value(json!({ - "v": 0, - "r": "0x2bdf47562da5f2a09f09cce70aed35ec9ac62f5377512b6a04cc427e0fda1f4d", - "s": "0x28f9311b515a5f17aa3ad5ea8bafaecfb0958801f01ca11fd593097b5087121b" - })) - .unwrap(); - let transaction = EthereumTransaction { essence, signature }; - - // verify the RLP roundtrip - let decoded = Transaction::decode_bytes(alloy_rlp::encode(&transaction)).unwrap(); - assert_eq!(transaction, decoded); - - // verify that bincode serialization works - let _: EthereumTransaction = - bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); - - assert_eq!( - transaction.hash(), - b256!("2bcdc03343ca9c050f8dfd3c87f32db718c762ae889f56762d8d8bdb7c5d69ff") - ); - let recovered = transaction.recover_from().unwrap(); - assert_eq!( - recovered, - address!("4b9f4114d50e7907bff87728a060ce8d53bf4cf7") - ); - } -} diff --git a/primitives/src/transactions/mod.rs b/primitives/src/transactions/mod.rs index 42a16f1f..10d6761e 100644 --- a/primitives/src/transactions/mod.rs +++ b/primitives/src/transactions/mod.rs @@ -14,232 +14,393 @@ use std::fmt::Debug; -use alloy_primitives::{Address, Bytes, TxHash}; +pub use alloy_consensus::{ + SignableTransaction, TxEip1559, TxEip2930, TxEip4844, TxEip4844Variant, + TxEnvelope as EthTxEnvelope, TxLegacy, +}; +use alloy_consensus::{Signed, Transaction}; +use alloy_network::eip2718::{Decodable2718, Eip2718Error, Encodable2718}; +use alloy_primitives::{TxKind, B256}; use alloy_rlp::{Decodable, Encodable}; -use anyhow::ensure; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; -use self::{ - optimism::{OptimismTxEssence, OPTIMISM_DEPOSITED_TX_TYPE}, - signature::TxSignature, -}; -use crate::{keccak::keccak, transactions::ethereum::EthereumTxEssence, U256}; +use self::optimism::{TxOptimismDeposit, OPTIMISM_DEPOSITED_TX_TYPE}; +use crate::RlpBytes; -pub mod ethereum; +// pub mod ethereum; pub mod optimism; -pub mod signature; - -pub type EthereumTransaction = Transaction; -pub type OptimismTransaction = Transaction; - -/// Represents a complete transaction, encompassing its core essence and the associated -/// signature. -/// -/// The `Transaction` struct encapsulates both the core details of the transaction (the -/// essence) and its cryptographic signature. The signature ensures the authenticity and -/// integrity of the transaction, confirming it was issued by the rightful sender. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct Transaction { - /// The core details of the transaction, which includes the data that is signed. - pub essence: E, - /// The cryptographic signature associated with the transaction, generated by signing - /// the transaction essence. - pub signature: TxSignature, -} - -/// Structs with this trait can be decoded from an RLP encoding containing additional -/// signature information. -pub trait SignedDecodable: Sized { - /// Decodes an instance of this struct and of `S` from the input RLP buffer. - fn decode_signed(buf: &mut &[u8]) -> alloy_rlp::Result<(Self, S)>; -} - -/// Represents the core details of a [Transaction], specifically the portion that gets -/// signed. -pub trait TxEssence: SignedDecodable + Encodable + Clone { - /// Returns the EIP-2718 transaction type or `0x00` for Legacy transactions. - fn tx_type(&self) -> u8; - /// Returns the gas limit set for the transaction. - /// - /// The gas limit represents the maximum amount of gas units that the transaction - /// is allowed to consume. It ensures that transactions don't run indefinitely. - fn gas_limit(&self) -> U256; - /// Returns the recipient address of the transaction, if available. - /// - /// For contract creation transactions, this method returns `None` as there's no - /// recipient address. - fn to(&self) -> Option
; - /// Recovers the Ethereum address of the sender from the transaction's signature. - /// - /// This method uses the ECDSA recovery mechanism to derive the sender's public key - /// and subsequently their Ethereum address. If the recovery is unsuccessful, an - /// error is returned. - fn recover_from(&self, signature: &TxSignature) -> anyhow::Result
; - /// Returns a reference to the transaction's call data - fn data(&self) -> &Bytes; - - /// Returns the length of the RLP-encoding payload in bytes. - fn payload_length(&self) -> usize; -} - -/// Provides RLP encoding functionality for [Transaction]. -impl Encodable for Transaction { - /// Encodes the [Transaction] struct into the provided `out` buffer. - /// - /// The encoding process starts by prepending the EIP-2718 transaction type, if - /// applicable. It then joins the RLP lists of the transaction essence and the - /// signature into a single list. This approach optimizes the encoding process by - /// reusing as much of the generated RLP code as possible. - #[inline] - fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { - let tx_type = self.essence.tx_type(); - // prepend the EIP-2718 transaction type for non-legacy transactions - if tx_type != 0 { - out.put_u8(tx_type); + +/// Represents a minimal EVM transaction. +pub trait EvmTransaction: Encodable + Decodable { + /// Recover `from`. + fn from(&self) -> Result; + /// Get `to`. + fn to(&self) -> TxKind; + /// Get `gas_limit`. + fn gas_limit(&self) -> u64; + /// Get `data`. + fn input(&self) -> &[u8]; + /// Returns the cached transaction hash. + fn hash(&self) -> B256; +} + +#[repr(u8)] +#[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord)] +pub enum TxType { + /// Legacy transaction type. + Legacy = 0, + /// EIP-2930 transaction type. + Eip2930 = 1, + /// EIP-1559 transaction type. + Eip1559 = 2, + /// EIP-4844 transaction type. + Eip4844 = 3, + /// Optimism deposited transaction type. + OptimismDeposit = OPTIMISM_DEPOSITED_TX_TYPE, +} + +impl TryFrom for TxType { + type Error = Eip2718Error; + + fn try_from(value: u8) -> Result { + match value { + // SAFETY: repr(u8) with explicit discriminant + 0..=3 => Ok(unsafe { std::mem::transmute(value) }), + OPTIMISM_DEPOSITED_TX_TYPE => Ok(TxType::OptimismDeposit), + _ => Err(Eip2718Error::UnexpectedType(value)), + } + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum TxEnvelope { + Ethereum(EthTxEnvelope), + /// An [`TxOptimismDeposited`]. + OptimismDeposit(TxOptimismDeposit), +} + +impl From> for TxEnvelope { + fn from(v: Signed) -> Self { + Self::Ethereum(EthTxEnvelope::Legacy(v)) + } +} + +impl From> for TxEnvelope { + fn from(v: Signed) -> Self { + Self::Ethereum(EthTxEnvelope::Eip2930(v)) + } +} + +impl From> for TxEnvelope { + fn from(v: Signed) -> Self { + Self::Ethereum(EthTxEnvelope::Eip1559(v)) + } +} + +impl From> for TxEnvelope { + fn from(v: Signed) -> Self { + let (tx, signature, hash) = v.into_parts(); + Self::Ethereum(EthTxEnvelope::Eip4844(Signed::new_unchecked( + TxEip4844Variant::TxEip4844(tx), + signature, + hash, + ))) + } +} + +impl TxEnvelope { + /// Return the [`TxType`] of the inner txn. + pub const fn tx_type(&self) -> TxType { + match self { + Self::Ethereum(eth) => match eth { + EthTxEnvelope::Legacy(_) => TxType::Legacy, + EthTxEnvelope::Eip2930(_) => TxType::Eip2930, + EthTxEnvelope::Eip1559(_) => TxType::Eip1559, + EthTxEnvelope::Eip4844(_) => TxType::Eip4844, + }, + Self::OptimismDeposit(_) => TxType::OptimismDeposit, + } + } +} + +impl EvmTransaction for TxEnvelope { + fn from(&self) -> Result { + match self { + Self::Ethereum(eth) => match eth { + EthTxEnvelope::Legacy(tx) => tx.recover_signer(), + EthTxEnvelope::Eip2930(tx) => tx.recover_signer(), + EthTxEnvelope::Eip1559(tx) => tx.recover_signer(), + EthTxEnvelope::Eip4844(tx) => tx.recover_signer(), + }, + Self::OptimismDeposit(tx) => Ok(tx.from()), + } + } + + fn to(&self) -> TxKind { + match self { + Self::Ethereum(eth) => match eth { + EthTxEnvelope::Legacy(tx) => tx.tx().to(), + EthTxEnvelope::Eip2930(tx) => tx.tx().to(), + EthTxEnvelope::Eip1559(tx) => tx.tx().to(), + EthTxEnvelope::Eip4844(tx) => tx.tx().to(), + }, + Self::OptimismDeposit(tx) => tx.to(), } - if tx_type == OPTIMISM_DEPOSITED_TX_TYPE { - // optimism deposited transactions have no signature - self.essence.encode(out); - return; + } + + fn gas_limit(&self) -> u64 { + match self { + Self::Ethereum(eth) => match eth { + EthTxEnvelope::Legacy(tx) => tx.tx().gas_limit(), + EthTxEnvelope::Eip2930(tx) => tx.tx().gas_limit(), + EthTxEnvelope::Eip1559(tx) => tx.tx().gas_limit(), + EthTxEnvelope::Eip4844(tx) => tx.tx().gas_limit(), + }, + Self::OptimismDeposit(tx) => tx.gas_limit(), } + } - // join the essence lists and the signature list into one - // this allows to reuse as much of the generated RLP code as possible - rlp_join_lists(&self.essence, &self.signature, out); + fn input(&self) -> &[u8] { + match self { + Self::Ethereum(eth) => match eth { + EthTxEnvelope::Legacy(tx) => tx.tx().input(), + EthTxEnvelope::Eip2930(tx) => tx.tx().input(), + EthTxEnvelope::Eip1559(tx) => tx.tx().input(), + EthTxEnvelope::Eip4844(tx) => tx.tx().input(), + }, + Self::OptimismDeposit(tx) => tx.input(), + } } - /// Computes the length of the RLP-encoded [Transaction] struct in bytes. - /// - /// The computed length includes the lengths of the encoded transaction essence and - /// signature. If the transaction type (as per EIP-2718) is not zero, an - /// additional byte is added to the length. - #[inline] - fn length(&self) -> usize { - let tx_type = self.essence.tx_type(); - let payload_length = if tx_type == OPTIMISM_DEPOSITED_TX_TYPE { - // optimism deposited transactions have no signature - self.essence.payload_length() - } else { - self.essence.payload_length() + self.signature.payload_length() - }; - - let mut length = payload_length + alloy_rlp::length_of_length(payload_length); - // add the EIP-2718 transaction type for non-legacy transactions - if tx_type != 0 { - length += 1; + fn hash(&self) -> B256 { + match self { + Self::Ethereum(eth) => match eth { + EthTxEnvelope::Legacy(tx) => *tx.hash(), + EthTxEnvelope::Eip2930(tx) => *tx.hash(), + EthTxEnvelope::Eip1559(tx) => *tx.hash(), + EthTxEnvelope::Eip4844(tx) => *tx.hash(), + }, + Self::OptimismDeposit(tx) => tx.hash_slow(), } - length } } -impl Decodable for Transaction { - fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { - E::decode_signed(buf).map(|(essence, signature)| Self { essence, signature }) +impl Serialize for TxEnvelope { + fn serialize(&self, serializer: S) -> Result { + let bytes = alloy_rlp::encode(self); + bytes.serialize(serializer) } } -impl Transaction { - /// Calculates the Keccak hash of the RLP-encoded transaction. - /// - /// This hash uniquely identifies the transaction on the Ethereum network. - #[inline] - pub fn hash(&self) -> TxHash { - keccak(alloy_rlp::encode(self)).into() +impl<'de> Deserialize<'de> for TxEnvelope { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let bytes = >::deserialize(deserializer)?; + Self::decode_bytes(bytes).map_err(serde::de::Error::custom) } +} - /// Recovers the Ethereum address of the sender from the transaction's signature. - /// - /// This method uses the ECDSA recovery mechanism to derive the sender's public key - /// and subsequently their Ethereum address. If the recovery is unsuccessful, an - /// error is returned. +impl Encodable for TxEnvelope { #[inline] - pub fn recover_from(&self) -> anyhow::Result
{ - self.essence.recover_from(&self.signature) + fn encode(&self, out: &mut dyn alloy_rlp::BufMut) { + self.encode_2718(out); + } + #[inline] + fn length(&self) -> usize { + self.encode_2718_len() } +} - /// Fully consumes the provided input RLP buffer to decode a Transaction instance - pub fn decode_strict(buf: &mut &[u8]) -> anyhow::Result { - let result = Self::decode(buf)?; - ensure!(buf.is_empty()); - Ok(result) +impl Decodable for TxEnvelope { + #[inline] + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + Self::decode_2718(buf) } } -/// Joins two RLP-encoded lists into a single RLP-encoded list. -/// -/// This function takes two RLP-encoded lists, decodes their headers to ensure they are -/// valid lists, and then combines their payloads into a single RLP-encoded list. The -/// resulting list is written to the provided `out` buffer. -/// -/// # Panics -/// -/// This function will panic if either `a` or `b` are not valid RLP-encoded lists. -fn rlp_join_lists(a: impl Encodable, b: impl Encodable, out: &mut dyn alloy_rlp::BufMut) { - let a_buf = alloy_rlp::encode(a); - let header = alloy_rlp::Header::decode(&mut &a_buf[..]).unwrap(); - if !header.list { - panic!("`a` not a list"); +impl Encodable2718 for TxEnvelope { + fn type_flag(&self) -> Option { + match self { + TxEnvelope::Ethereum(eth) => Encodable2718::type_flag(eth), + TxEnvelope::OptimismDeposit(_) => Some(OPTIMISM_DEPOSITED_TX_TYPE), + } + } + + fn encode_2718_len(&self) -> usize { + match self { + TxEnvelope::Ethereum(eth) => Encodable2718::encode_2718_len(eth), + TxEnvelope::OptimismDeposit(tx) => 1 + tx.length(), + } + } + + fn encode_2718(&self, out: &mut dyn bytes::BufMut) { + match self { + TxEnvelope::Ethereum(eth) => Encodable2718::encode_2718(eth, out), + TxEnvelope::OptimismDeposit(tx) => { + out.put_u8(OPTIMISM_DEPOSITED_TX_TYPE); + tx.encode(out); + } + } } - let a_head_length = header.length(); - let a_payload_length = a_buf.len() - a_head_length; +} - let b_buf = alloy_rlp::encode(b); - let header = alloy_rlp::Header::decode(&mut &b_buf[..]).unwrap(); - if !header.list { - panic!("`b` not a list"); +impl Decodable2718 for TxEnvelope { + fn typed_decode(ty: u8, buf: &mut &[u8]) -> alloy_rlp::Result { + match ty { + OPTIMISM_DEPOSITED_TX_TYPE => Ok(Self::OptimismDeposit(Decodable::decode(buf)?)), + _ => Ok(TxEnvelope::Ethereum(EthTxEnvelope::typed_decode(ty, buf)?)), + } } - let b_head_length = header.length(); - let b_payload_length = b_buf.len() - b_head_length; - alloy_rlp::Header { - list: true, - payload_length: a_payload_length + b_payload_length, + fn fallback_decode(buf: &mut &[u8]) -> alloy_rlp::Result { + Ok(TxEnvelope::Ethereum(EthTxEnvelope::fallback_decode(buf)?)) } - .encode(out); - out.put_slice(&a_buf[a_head_length..]); // skip the header - out.put_slice(&b_buf[b_head_length..]); // skip the header } #[cfg(test)] mod tests { - use serde_json::json; + use alloy_primitives::{address, b256, Bytes}; + use hex_literal::hex; use super::*; - use crate::{transactions::EthereumTransaction, RlpBytes}; + use crate::RlpBytes; + + #[test] + fn legacy() { + // Tx: 0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060 + let raw_tx = hex!("f86780862d79883d2000825208945df9b87991262f6ba471f09758cde1c0fc1de734827a69801ca088ff6cf0fefd94db46111149ae4bfc179e9b94721fffd821d38d16464b3f71d0a045e0aff800961cfce805daef7016b9b675c137a6a41a548f7b60a3484c06a33a"); + let tx = TxEnvelope::decode_2718(&mut raw_tx.as_slice()).unwrap(); + assert_eq!(tx.encode_2718_len(), raw_tx.len()); + println!("{:#?}", tx); + + // verify the RLP roundtrip + let decoded = TxEnvelope::decode_bytes(alloy_rlp::encode(&tx)).unwrap(); + assert_eq!(tx, decoded); + // test the bincode roundtrip + let _: TxEnvelope = bincode::deserialize(&bincode::serialize(&tx).unwrap()).unwrap(); + + assert_eq!( + tx.hash(), + b256!("5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060") + ); + assert_eq!( + tx.from().unwrap(), + address!("A1E4380A3B1f749673E270229993eE55F35663b4") + ); + } #[test] - fn rlp_length() { - let tx = json!({ - "essence": { - "Legacy": { - "nonce": 537760, - "gas_price": "0x03c49bfa04", - "gas_limit": "0x019a28", - "to": { "Call": "0xf0ee707731d1be239f9f482e1b2ea5384c0c426f" }, - "value": "0x06df842eaa9fb800", - "data": "0x", - "chain_id": 1 - } - }, - "signature": { - "v": 38, - "r": "0xcadd790a37b78e5613c8cf44dc3002e3d7f06a5325d045963c708efe3f9fdf7a", - "s": "0x1f63adb9a2d5e020c6aa0ff64695e25d7d9a780ed8471abe716d2dc0bf7d4259" - } - }); - let transaction: EthereumTransaction = serde_json::from_value(tx).unwrap(); + fn eip155() { + // Tx: 0x4540eb9c46b1654c26353ac3c65e56451f711926982ce1b02f15c50e7459caf7 + let raw_tx = hex!("f870830834a08503c49bfa0483019a2894f0ee707731d1be239f9f482e1b2ea5384c0c426f8806df842eaa9fb8008026a0cadd790a37b78e5613c8cf44dc3002e3d7f06a5325d045963c708efe3f9fdf7aa01f63adb9a2d5e020c6aa0ff64695e25d7d9a780ed8471abe716d2dc0bf7d4259"); + let tx = TxEnvelope::decode_2718(&mut raw_tx.as_slice()).unwrap(); + assert_eq!(tx.encode_2718_len(), raw_tx.len()); + println!("{:#?}", tx); // verify the RLP roundtrip - let decoded = Transaction::decode_bytes(alloy_rlp::encode(&transaction)).unwrap(); - assert_eq!(transaction, decoded); + let decoded = TxEnvelope::decode_bytes(alloy_rlp::encode(&tx)).unwrap(); + assert_eq!(tx, decoded); - let encoded = alloy_rlp::encode(&transaction.essence); - assert_eq!(encoded.len(), transaction.essence.length()); + assert_eq!( + tx.hash(), + b256!("4540eb9c46b1654c26353ac3c65e56451f711926982ce1b02f15c50e7459caf7") + ); + assert_eq!( + tx.from().unwrap(), + address!("974CaA59e49682CdA0AD2bbe82983419A2ECC400") + ); + } + + #[test] + fn eip2930() { + // Tx: 0xbe4ef1a2244e99b1ef518aec10763b61360be22e3b649dcdf804103719b1faef + let raw_tx = hex!("01f903050183016e97850f46a5a9d88302167094c11ce44147c9f6149fbe54adb0588523c38718d784010d1471b841050000000002b8809aef26206090eafd7d5688615d48197d1c5ce09be6c30a33be4c861dee44d13f6dd33c2e8c5cad7e2725f88a8f0000000002d67ca5eb0e5fb6f90253f87a94d6e64961ba13ba42858ad8a74ed9a9b051a4957df863a00000000000000000000000000000000000000000000000000000000000000008a00b4b38935f88a7bddbe6be76893de2a04640a55799d6160729a82349aff1ffaea0c59ee2ee2ba599569b2b1f06989dadbec5ee157c8facfe64f36a3e33c2b9d1bff87a94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f863a07635825e4f8dfeb20367f8742c8aac958a66caa001d982b3a864dcc84167be80a042555691810bdf8f236c31de88d2cc9407a8ff86cd230ba3b7029254168df92aa029ece5a5f4f3e7751868475502ab752b5f5fa09010960779bf7204deb72f5ddef89b944c861dee44d13f6dd33c2e8c5cad7e2725f88a8ff884a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8bc9490eafd7d5688615d48197d1c5ce09be6c30a33bef8a5a00000000000000000000000000000000000000000000000000000000000000001a09c04773acff4c5c42718bd0120c72761f458e43068a3961eb935577d1ed4effba00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000401a0f86aa2dfde99b0d6a41741e96cfcdee0c6271febd63be4056911db19ae347e66a0601deefbc4835cb15aa1af84af6436fc692dea3428d53e7ff3d34a314cefe7fc"); + let tx = TxEnvelope::decode_2718(&mut raw_tx.as_slice()).unwrap(); + assert_eq!(tx.encode_2718_len(), raw_tx.len()); + println!("{:#?}", tx); + + // verify the RLP roundtrip + let decoded = TxEnvelope::decode_bytes(alloy_rlp::encode(&tx)).unwrap(); + assert_eq!(tx, decoded); + + assert_eq!( + tx.hash(), + b256!("be4ef1a2244e99b1ef518aec10763b61360be22e3b649dcdf804103719b1faef") + ); + assert_eq!( + tx.from().unwrap(), + address!("79b7a69d90c82E014Bf0315e164208119B510FA0") + ); + } + + #[test] + fn eip1559() { + // Tx: 0x2bcdc03343ca9c050f8dfd3c87f32db718c762ae889f56762d8d8bdb7c5d69ff + let raw_tx = hex!("02f8730120843b9aca0085089d5f3200825b0494a9d1e08c7793af67e9d92fe308d5697fb81d3e438801dd1f234f68cde280c080a02bdf47562da5f2a09f09cce70aed35ec9ac62f5377512b6a04cc427e0fda1f4da028f9311b515a5f17aa3ad5ea8bafaecfb0958801f01ca11fd593097b5087121b"); + let tx = TxEnvelope::decode_2718(&mut raw_tx.as_slice()).unwrap(); + assert_eq!(tx.encode_2718_len(), raw_tx.len()); + println!("{:#?}", tx); + + // verify the RLP roundtrip + let decoded = TxEnvelope::decode_bytes(alloy_rlp::encode(&tx)).unwrap(); + assert_eq!(tx, decoded); - let encoded = alloy_rlp::encode(&transaction.signature); - assert_eq!(encoded.len(), transaction.signature.length()); + assert_eq!( + tx.hash(), + b256!("2bcdc03343ca9c050f8dfd3c87f32db718c762ae889f56762d8d8bdb7c5d69ff") + ); + assert_eq!( + tx.from().unwrap(), + address!("4b9f4114D50e7907BFF87728A060Ce8d53Bf4CF7") + ); + } + + #[test] + fn eip4844() { + // Tx: 0x25f463005fb95770cfe9fffd857dc6b20878b32fa179cd235552027898da0c8e + let raw_tx = hex!("03f89883aa36a7820348843b9aca008502568f7a7682520894ff000000000000000000000000000000111554218080c08508e82ced46e1a00153f8e9343d99868798a9b41d4fe990c5384db8b0fd68a9189ecf1f9a6deec780a0c9fb7d6c3ade31a242dfaf2004cec17ddb82c24f7ff7516a519b27bb7f8f7808a01674813859d3b1e282b7789391896cf9945349cf05d8550ab81f3a2cdc99dc12"); + let tx = TxEnvelope::decode_2718(&mut raw_tx.as_slice()).unwrap(); + assert_eq!(tx.encode_2718_len(), raw_tx.len()); + println!("{:#?}", tx); + + // verify the RLP roundtrip + println!("{:?}", Bytes::from(alloy_rlp::encode(&tx))); + let decoded = TxEnvelope::decode_bytes(alloy_rlp::encode(&tx)).unwrap(); + assert_eq!(tx, decoded); + + assert_eq!( + tx.hash(), + b256!("25f463005fb95770cfe9fffd857dc6b20878b32fa179cd235552027898da0c8e") + ); + assert_eq!( + tx.from().unwrap(), + address!("19CC7073150D9f5888f09E0e9016d2a39667df14") + ); + } + + #[test] + fn optimism_deposited() { + // Tx: 0x2bf9119d4faa19593ca1b3cda4b4ac03c0ced487454a50fbdcd09aebe21210e3 + let raw_tx = hex!("7ef90209a020b925f36904e1e62099920d902925817c4357e9f674b8b14d133631961390109436bde71c97b33cc4729cf772ae268934f7ab70b294420000000000000000000000000000000000000788030d98d59a96000088030d98d59a96000083077d2e80b901a4d764ad0b000100000000000000000000000000000000000000000000000000000000af8600000000000000000000000099c9fc46f92e8a1c0dec1b1747d010903e884be10000000000000000000000004200000000000000000000000000000000000010000000000000000000000000000000000000000000000000030d98d59a9600000000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000a41635f5fd000000000000000000000000ab12275f2d91f87b301a4f01c9af4e83b3f45baa000000000000000000000000ab12275f2d91f87b301a4f01c9af4e83b3f45baa000000000000000000000000000000000000000000000000030d98d59a9600000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + let tx = TxEnvelope::decode_2718(&mut raw_tx.as_slice()).unwrap(); + assert_eq!(tx.encode_2718_len(), raw_tx.len()); + println!("{:#?}", tx); + + // verify the RLP roundtrip + let encoded = alloy_rlp::encode(&tx); + assert_eq!(encoded.len(), tx.length()); + let decoded = TxEnvelope::decode_bytes(encoded).unwrap(); + assert_eq!(tx, decoded); - let encoded = alloy_rlp::encode(&transaction); - assert_eq!(encoded.len(), transaction.length()); + assert_eq!( + tx.hash(), + b256!("2bf9119d4faa19593ca1b3cda4b4ac03c0ced487454a50fbdcd09aebe21210e3") + ); + assert_eq!( + tx.from().unwrap(), + address!("36bde71c97b33cc4729cf772ae268934f7ab70b2") + ); } } diff --git a/primitives/src/transactions/optimism.rs b/primitives/src/transactions/optimism.rs index 097cdf03..ccaa0fd1 100644 --- a/primitives/src/transactions/optimism.rs +++ b/primitives/src/transactions/optimism.rs @@ -12,244 +12,114 @@ // See the License for the specific language governing permissions and // limitations under the License. -use alloy_primitives::{Address, Bytes, B256, U256}; -use alloy_rlp::{Decodable, Encodable}; +use alloy_consensus::Transaction; +use alloy_primitives::{keccak256, Address, Bytes, ChainId, TxKind, B256, U256}; +use alloy_rlp::Encodable; use alloy_rlp_derive::{RlpDecodable, RlpEncodable}; -use bytes::{Buf, BufMut}; -use serde::{Deserialize, Serialize}; - -use super::signature::TxSignature; -use crate::transactions::{ - ethereum::{EthereumTxEssence, TransactionKind}, - SignedDecodable, TxEssence, -}; +use bytes::BufMut; /// The EIP-2718 transaction type for an Optimism deposited transaction. pub const OPTIMISM_DEPOSITED_TX_TYPE: u8 = 0x7E; /// Represents an Optimism depositing transaction that is a L2 transaction that was /// derived from L1 and included in a L2 block. -#[derive( - Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable, -)] -pub struct TxEssenceOptimismDeposited { +#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, RlpEncodable, RlpDecodable)] +pub struct TxOptimismDeposit { /// The source hash which uniquely identifies the origin of the deposit. pub source_hash: B256, /// The 160-bit address of the sender. pub from: Address, /// The 160-bit address of the intended recipient for a message call or - /// [TransactionKind::Create] for contract creation. - pub to: TransactionKind, + /// [TxKind::Create] for contract creation. + pub to: TxKind, /// The ETH value to mint on L2. pub mint: U256, /// The amount, in Wei, to be transferred to the recipient of the message call. pub value: U256, /// The maximum amount of gas allocated for the execution of the L2 transaction. - pub gas_limit: U256, + pub gas_limit: u64, /// If true, the transaction does not interact with the L2 block gas pool. pub is_system_tx: bool, /// The transaction's payload, represented as a variable-length byte array. - pub data: Bytes, + pub input: Bytes, } -/// Represents the core essence of an Optimism transaction, specifically the portion that -/// gets signed. -/// -/// The [OptimismTxEssence] enum provides a way to handle different types of Optimism -/// transactions. -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub enum OptimismTxEssence { - /// Represents an Ethereum-compatible L2 transaction. - Ethereum(EthereumTxEssence), - /// Represents an Optimism depositing transaction. - OptimismDeposited(TxEssenceOptimismDeposited), -} +impl TxOptimismDeposit { + /// Get transaction type + pub const fn tx_type(&self) -> u8 { + OPTIMISM_DEPOSITED_TX_TYPE + } -impl Encodable for OptimismTxEssence { - /// Encodes the [OptimismTxEssence] enum variant into the provided `out` buffer. - #[inline] - fn encode(&self, out: &mut dyn BufMut) { - match self { - OptimismTxEssence::Ethereum(eth) => eth.encode(out), - OptimismTxEssence::OptimismDeposited(op) => op.encode(out), - } + pub fn source_hash(&self) -> B256 { + self.source_hash } - /// Computes the length of the RLP-encoded [OptimismTxEssence] enum variant in bytes. - #[inline] - fn length(&self) -> usize { - match self { - OptimismTxEssence::Ethereum(eth) => eth.length(), - OptimismTxEssence::OptimismDeposited(op) => op.length(), - } + pub fn from(&self) -> Address { + self.from } -} -impl SignedDecodable for OptimismTxEssence { - fn decode_signed(buf: &mut &[u8]) -> alloy_rlp::Result<(Self, TxSignature)> { - match buf.first().copied() { - Some(0x7e) => { - buf.advance(1); - Ok(( - OptimismTxEssence::OptimismDeposited(TxEssenceOptimismDeposited::decode(buf)?), - TxSignature::default(), - )) - } - Some(_) => EthereumTxEssence::decode_signed(buf) - .map(|(e, s)| (OptimismTxEssence::Ethereum(e), s)), - None => Err(alloy_rlp::Error::InputTooShort), - } + pub fn hash_slow(&self) -> B256 { + let mut buf = Vec::with_capacity(self.length() + 1); + buf.put_u8(self.tx_type()); + self.encode(&mut buf); + keccak256(&buf) } } -impl TxEssence for OptimismTxEssence { - /// Returns the EIP-2718 transaction type. - fn tx_type(&self) -> u8 { - match self { - OptimismTxEssence::Ethereum(eth) => eth.tx_type(), - OptimismTxEssence::OptimismDeposited(_) => OPTIMISM_DEPOSITED_TX_TYPE, - } +impl Transaction for TxOptimismDeposit { + fn input(&self) -> &[u8] { + &self.input + } + + fn to(&self) -> TxKind { + self.to } - /// Returns the gas limit set for the transaction. - fn gas_limit(&self) -> U256 { - match self { - OptimismTxEssence::Ethereum(eth) => eth.gas_limit(), - OptimismTxEssence::OptimismDeposited(op) => op.gas_limit, - } + + fn value(&self) -> U256 { + self.value } - /// Returns the recipient address of the transaction, if available. - fn to(&self) -> Option
{ - match self { - OptimismTxEssence::Ethereum(eth) => eth.to(), - OptimismTxEssence::OptimismDeposited(op) => op.to.into(), - } + + fn chain_id(&self) -> Option { + None } - /// Recovers the Ethereum address of the sender from the transaction's signature. - fn recover_from(&self, signature: &TxSignature) -> anyhow::Result
{ - match self { - OptimismTxEssence::Ethereum(eth) => eth.recover_from(signature), - OptimismTxEssence::OptimismDeposited(op) => Ok(op.from), - } + + fn nonce(&self) -> u64 { + 0 } - /// Returns the length of the RLP-encoding payload in bytes. - fn payload_length(&self) -> usize { - match self { - OptimismTxEssence::Ethereum(eth) => eth.payload_length(), - OptimismTxEssence::OptimismDeposited(op) => op._alloy_rlp_payload_length(), - } + + fn gas_limit(&self) -> u64 { + self.gas_limit } - /// Returns a reference to the transaction's call data - fn data(&self) -> &Bytes { - match self { - OptimismTxEssence::Ethereum(eth) => eth.data(), - OptimismTxEssence::OptimismDeposited(op) => &op.data, - } + + fn gas_price(&self) -> Option { + None } } #[cfg(test)] mod tests { use alloy_primitives::{address, b256}; - use serde_json::json; + use hex_literal::hex; use super::*; - use crate::{ - transactions::{OptimismTransaction, Transaction}, - RlpBytes, - }; - - #[test] - fn ethereum() { - // Tx: 0x9125dcdf2a82f349bbcd8c1201cc601b7b4f98975c76d1f8ee3ce9270334fb8a - let tx = json!({ - "Ethereum": { - "Eip1559": { - "chain_id": 10, - "nonce": 17, - "max_priority_fee_per_gas": "0x3b9cdd02", - "max_fee_per_gas": "0x3b9cdd02", - "gas_limit": "0x01a1a7", - "to": { "Call": "0x7f5c764cbc14f9669b88837ca1490cca17c31607" }, - "value": "0x0", - "data": "0x095ea7b30000000000000000000000004c5d5234f232bd2d76b96aa33f5ae4fcf0e4bfabffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", - "access_list": [] - } - } - }); - let essence: OptimismTxEssence = serde_json::from_value(tx).unwrap(); - - let signature: TxSignature = serde_json::from_value(json!({ - "v": 0, - "r": "0x044e091fe419b233ddc76c616f60f33f5c68a5d6ea315b0b22afdbe5af66b9e6", - "s": "0x7f00ccbff42777c6c2e5d5e85579a7984783be446cc1b9a7b8e080d167d56fa8" - })) - .unwrap(); - - let transaction = OptimismTransaction { essence, signature }; - - // verify the RLP roundtrip - let decoded = Transaction::decode_bytes(alloy_rlp::encode(&transaction)).unwrap(); - assert_eq!(transaction, decoded); - - // verify that bincode serialization works - let _: OptimismTransaction = - bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); - - let encoded = alloy_rlp::encode(&transaction); - assert_eq!(encoded.len(), transaction.length()); - - assert_eq!( - transaction.hash(), - b256!("9125dcdf2a82f349bbcd8c1201cc601b7b4f98975c76d1f8ee3ce9270334fb8a") - ); - let recovered = transaction.recover_from().unwrap(); - assert_eq!( - recovered, - address!("96dd9c6f1fd5b3fbaa70898f09bedff903237d6d") - ); - } #[test] fn optimism_deposited() { // Tx: 0x2bf9119d4faa19593ca1b3cda4b4ac03c0ced487454a50fbdcd09aebe21210e3 - let tx = json!({ - "OptimismDeposited": { - "source_hash": "0x20b925f36904e1e62099920d902925817c4357e9f674b8b14d13363196139010", - "from": "0x36bde71c97b33cc4729cf772ae268934f7ab70b2", - "to": { "Call": "0x4200000000000000000000000000000000000007" }, - "mint": "0x030d98d59a960000", - "value": "0x030d98d59a960000", - "gas_limit": "0x077d2e", - "is_system_tx": false, - "data": "0xd764ad0b000100000000000000000000000000000000000000000000000000000000af8600000000000000000000000099c9fc46f92e8a1c0dec1b1747d010903e884be10000000000000000000000004200000000000000000000000000000000000010000000000000000000000000000000000000000000000000030d98d59a9600000000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000a41635f5fd000000000000000000000000ab12275f2d91f87b301a4f01c9af4e83b3f45baa000000000000000000000000ab12275f2d91f87b301a4f01c9af4e83b3f45baa000000000000000000000000000000000000000000000000030d98d59a9600000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - } - }); - let essence: OptimismTxEssence = serde_json::from_value(tx).unwrap(); - - let transaction = OptimismTransaction { - essence, - signature: TxSignature::default(), + let tx = TxOptimismDeposit { + source_hash: b256!("20b925f36904e1e62099920d902925817c4357e9f674b8b14d13363196139010"), + from: address!("36bde71c97b33cc4729cf772ae268934f7ab70b2"), + to: TxKind::Call(address!("4200000000000000000000000000000000000007")), + mint: U256::from(0x030d98d59a960000u64), + value: U256::from(0x030d98d59a960000u64), + gas_limit: 0x077d2e, + is_system_tx: false, + input: Bytes::from(hex!("d764ad0b000100000000000000000000000000000000000000000000000000000000af8600000000000000000000000099c9fc46f92e8a1c0dec1b1747d010903e884be10000000000000000000000004200000000000000000000000000000000000010000000000000000000000000000000000000000000000000030d98d59a9600000000000000000000000000000000000000000000000000000000000000030d4000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000000a41635f5fd000000000000000000000000ab12275f2d91f87b301a4f01c9af4e83b3f45baa000000000000000000000000ab12275f2d91f87b301a4f01c9af4e83b3f45baa000000000000000000000000000000000000000000000000030d98d59a9600000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000") ), }; - // verify the RLP roundtrip - let decoded = Transaction::decode_bytes(alloy_rlp::encode(&transaction)).unwrap(); - assert_eq!(transaction, decoded); - - // verify that bincode serialization works - let _: OptimismTransaction = - bincode::deserialize(&bincode::serialize(&transaction).unwrap()).unwrap(); - - let encoded = alloy_rlp::encode(&transaction); - assert_eq!(encoded.len(), transaction.length()); - assert_eq!( - transaction.hash(), + tx.hash_slow(), b256!("2bf9119d4faa19593ca1b3cda4b4ac03c0ced487454a50fbdcd09aebe21210e3") ); - let recovered = transaction.recover_from().unwrap(); - assert_eq!( - recovered, - address!("36bde71c97b33cc4729cf772ae268934f7ab70b2") - ); } } diff --git a/primitives/src/transactions/signature.rs b/primitives/src/transactions/signature.rs deleted file mode 100644 index bf056a74..00000000 --- a/primitives/src/transactions/signature.rs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright 2024 RISC Zero, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -use alloy_primitives::{ChainId, U256}; -use alloy_rlp_derive::{RlpDecodable, RlpEncodable, RlpMaxEncodedLen}; -use serde::{Deserialize, Serialize}; - -/// Represents a cryptographic signature associated with a transaction. -/// -/// The `TxSignature` struct encapsulates the components of an ECDSA signature: `v`, `r`, -/// and `s`. This signature can be used to recover the public key of the signer, ensuring -/// the authenticity of the transaction. -#[derive( - Debug, - Clone, - Default, - PartialEq, - Eq, - Serialize, - Deserialize, - RlpEncodable, - RlpMaxEncodedLen, - RlpDecodable, -)] -pub struct TxSignature { - pub v: u64, - pub r: U256, - pub s: U256, -} - -impl TxSignature { - /// Returns the chain_id of the V value, if any. - pub fn chain_id(&self) -> Option { - match self.v { - // EIP-155 encodes the chain_id in the V value - value @ 35..=u64::MAX => Some((value - 35) / 2), - _ => None, - } - } - - /// Computes the length of the RLP-encoded signature payload in bytes. - pub fn payload_length(&self) -> usize { - self._alloy_rlp_payload_length() - } -} diff --git a/testing/ef-tests/src/ethers.rs b/testing/ef-tests/src/ethers.rs index df9a3e36..5ee8e78d 100644 --- a/testing/ef-tests/src/ethers.rs +++ b/testing/ef-tests/src/ethers.rs @@ -53,15 +53,15 @@ impl Provider for TestProvider { logs_bloom: Some(Bloom::from_slice(self.header.logs_bloom.as_slice())), difficulty: self.header.difficulty.to_be_bytes().into(), number: Some(self.header.number.into()), - gas_limit: self.header.gas_limit.to_be_bytes().into(), - gas_used: self.header.gas_used.to_be_bytes().into(), - timestamp: self.header.timestamp.to_be_bytes().into(), + gas_limit: self.header.gas_limit.into(), + gas_used: self.header.gas_used.into(), + timestamp: self.header.timestamp.into(), extra_data: self.header.extra_data.0.clone().into(), mix_hash: Some(self.header.mix_hash.0.into()), - nonce: Some(self.header.nonce.0.into()), - base_fee_per_gas: Some(self.header.base_fee_per_gas.to_be_bytes().into()), + nonce: Some(self.header.nonce.to_be_bytes().into()), + base_fee_per_gas: self.header.base_fee_per_gas.map(U256::from), withdrawals_root: self.header.withdrawals_root.map(|r| r.0.into()), - hash: Some(self.header.hash().0.into()), + hash: Some(self.header.hash_slow().0.into()), ..Default::default() }) } diff --git a/testing/ef-tests/src/ethtests.rs b/testing/ef-tests/src/ethtests.rs index bcb84a3b..2d908c94 100644 --- a/testing/ef-tests/src/ethtests.rs +++ b/testing/ef-tests/src/ethtests.rs @@ -16,12 +16,13 @@ use std::{fs::File, io::BufReader, path::PathBuf}; use revm::primitives::SpecId; use serde_json::Value; -use zeth_lib::consts::{ChainSpec, ETH_MAINNET_EIP1559_CONSTANTS}; -use zeth_primitives::block::Header; +use zeth_lib::consts::{ChainSpec, ETH_MAINNET_CHAIN_SPEC, ETH_MAINNET_EIP1559_CONSTANTS}; +use zeth_primitives::Header; use crate::TestJson; pub struct EthTestCase { + pub name: String, pub json: TestJson, pub genesis: Header, pub chain_spec: ChainSpec, @@ -36,21 +37,20 @@ pub fn read_eth_test(path: PathBuf) -> Vec { .unwrap() .into_iter() .filter_map(|(name, test)| { - println!("test '{}'", name); let json: TestJson = serde_json::from_value(test.take()).unwrap(); - let spec: SpecId = json.network.as_str().into(); - // skip tests with an unsupported network version - if spec < SpecId::MERGE || spec > SpecId::SHANGHAI { - println!("skipping ({})", json.network); + let spec: SpecId = json.network.replace("Paris", "Merge").as_str().into(); + if let Err(err) = ETH_MAINNET_CHAIN_SPEC.validate_spec_id(spec) { + println!("skipping '{}': {}", name, err); return None; } let chain_spec = ChainSpec::new_single(1, spec, ETH_MAINNET_EIP1559_CONSTANTS); let genesis: Header = json.genesis.clone().into(); - assert_eq!(genesis.hash(), json.genesis.hash); + assert_eq!(genesis.hash_slow(), json.genesis.hash); Some(EthTestCase { + name: name.clone(), json, genesis, chain_spec, diff --git a/testing/ef-tests/src/lib.rs b/testing/ef-tests/src/lib.rs index 1bf8a69a..9c3c856a 100644 --- a/testing/ef-tests/src/lib.rs +++ b/testing/ef-tests/src/lib.rs @@ -32,19 +32,12 @@ use zeth_lib::{ use zeth_primitives::{ access_list::{AccessList, AccessListItem}, alloy_rlp, - block::Header, ethers::from_ethers_h160, keccak::keccak, - transactions::{ - ethereum::{ - EthereumTxEssence, TransactionKind, TxEssenceEip1559, TxEssenceEip2930, TxEssenceLegacy, - }, - signature::TxSignature, - EthereumTransaction, - }, + transactions::{SignableTransaction, TxEip1559, TxEip2930, TxEip4844, TxEnvelope, TxLegacy}, trie::{self, MptNode, MptNodeData, StateAccount}, withdrawal::Withdrawal, - Address, Bloom, Bytes, StorageKey, B256, B64, U256, U64, + Address, Bloom, Bytes, Header, Signature, StorageKey, B256, B64, U128, U256, U64, U8, }; use crate::ethers::TestProvider; @@ -79,8 +72,7 @@ pub struct TestBlock { #[serde(default)] pub transactions: Vec, #[serde(default)] - pub uncle_headers: Vec, - pub withdrawals: Option>, + pub withdrawals: Vec, } #[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] @@ -128,21 +120,24 @@ impl From<&ProviderDb> for TestState { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TestHeader { - pub base_fee_per_gas: Option, + pub base_fee_per_gas: Option, + pub blob_gas_used: Option, pub bloom: Bloom, pub coinbase: Address, - pub extra_data: Bytes, pub difficulty: U256, - pub gas_limit: U256, - pub gas_used: U256, + pub excess_blob_gas: Option, + pub extra_data: Bytes, + pub gas_limit: U64, + pub gas_used: U64, pub hash: B256, pub mix_hash: B256, pub nonce: B64, pub number: U64, + pub parent_beacon_block_root: Option, pub parent_hash: B256, pub receipt_trie: B256, pub state_root: B256, - pub timestamp: U256, + pub timestamp: U64, pub transactions_trie: B256, pub uncle_hash: B256, pub withdrawals_root: Option, @@ -160,14 +155,17 @@ impl From for Header { logs_bloom: header.bloom, difficulty: header.difficulty, number: header.number.try_into().unwrap(), - gas_limit: header.gas_limit, - gas_used: header.gas_used, - timestamp: header.timestamp, + gas_limit: header.gas_limit.try_into().unwrap(), + gas_used: header.gas_used.try_into().unwrap(), + timestamp: header.timestamp.try_into().unwrap(), extra_data: header.extra_data, mix_hash: header.mix_hash, - nonce: header.nonce, - base_fee_per_gas: header.base_fee_per_gas.unwrap(), + nonce: header.nonce.into(), + base_fee_per_gas: header.base_fee_per_gas.map(|v| v.try_into().unwrap()), withdrawals_root: header.withdrawals_root, + blob_gas_used: header.blob_gas_used.map(|v| v.try_into().unwrap()), + excess_blob_gas: header.excess_blob_gas.map(|v| v.try_into().unwrap()), + parent_beacon_block_root: header.parent_beacon_block_root, } } } @@ -176,72 +174,84 @@ impl From for Header { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct TestTransaction { - pub data: Bytes, pub access_list: Option, - pub gas_limit: U256, - pub gas_price: Option, - pub max_fee_per_gas: Option, - pub max_priority_fee_per_gas: Option, - pub value: U256, + pub blob_versioned_hashes: Option>, + pub chain_id: Option, + pub data: Bytes, + pub gas_limit: U64, + pub gas_price: Option, + pub max_fee_per_blob_gas: Option, + pub max_fee_per_gas: Option, + pub max_priority_fee_per_gas: Option, + pub nonce: U64, #[serde_as(as = "NoneAsEmptyString")] pub to: Option
, - pub nonce: U64, + #[serde(rename = "type")] + pub type_id: Option, + pub value: U256, pub v: U64, pub r: U256, pub s: U256, } -impl From for EthereumTransaction { +impl From for TxEnvelope { fn from(tx: TestTransaction) -> Self { - let signature = TxSignature { - v: tx.v.try_into().unwrap(), - r: tx.r, - s: tx.s, - }; - let essence = if tx.access_list.is_none() { - EthereumTxEssence::Legacy(TxEssenceLegacy { - chain_id: None, + let signature = Signature::from_rs_and_parity(tx.r, tx.s, tx.v).unwrap(); + match tx.type_id.map(|v| u8::try_from(v).unwrap()) { + None | Some(0) => TxLegacy { + chain_id: signature.v().chain_id(), // derive chain ID from signature + nonce: tx.nonce.try_into().unwrap(), + gas_price: tx.gas_price.unwrap().try_into().unwrap(), + gas_limit: tx.gas_limit.try_into().unwrap(), + to: tx.to.into(), + value: tx.value, + input: tx.data, + } + .into_signed(signature) + .into(), + + Some(1) => TxEip2930 { + chain_id: tx.chain_id.unwrap().try_into().unwrap(), nonce: tx.nonce.try_into().unwrap(), - gas_price: tx.gas_price.unwrap(), - gas_limit: tx.gas_limit, - to: match tx.to { - Some(addr) => TransactionKind::Call(addr), - None => TransactionKind::Create, - }, + gas_price: tx.gas_price.unwrap().try_into().unwrap(), + gas_limit: tx.gas_limit.try_into().unwrap(), + to: tx.to.into(), value: tx.value, - data: tx.data, - }) - } else if tx.max_fee_per_gas.is_none() { - EthereumTxEssence::Eip2930(TxEssenceEip2930 { - chain_id: 1, + input: tx.data, + access_list: tx.access_list.unwrap().into(), + } + .into_signed(signature) + .into(), + Some(2) => TxEip1559 { + chain_id: tx.chain_id.unwrap().try_into().unwrap(), nonce: tx.nonce.try_into().unwrap(), - gas_price: tx.gas_price.unwrap(), - gas_limit: tx.gas_limit, - to: match tx.to { - Some(addr) => TransactionKind::Call(addr), - None => TransactionKind::Create, - }, + max_priority_fee_per_gas: tx.max_priority_fee_per_gas.unwrap().try_into().unwrap(), + max_fee_per_gas: tx.max_fee_per_gas.unwrap().try_into().unwrap(), + gas_limit: tx.gas_limit.try_into().unwrap(), + to: tx.to.into(), value: tx.value, - data: tx.data, + input: tx.data, access_list: tx.access_list.unwrap().into(), - }) - } else { - EthereumTxEssence::Eip1559(TxEssenceEip1559 { - chain_id: 1, + } + .into_signed(signature) + .into(), + Some(3) => TxEip4844 { + chain_id: tx.chain_id.unwrap().try_into().unwrap(), nonce: tx.nonce.try_into().unwrap(), - max_priority_fee_per_gas: tx.max_priority_fee_per_gas.unwrap(), - max_fee_per_gas: tx.max_fee_per_gas.unwrap(), - gas_limit: tx.gas_limit, - to: match tx.to { - Some(addr) => TransactionKind::Call(addr), - None => TransactionKind::Create, - }, + gas_limit: tx.gas_limit.try_into().unwrap(), + max_fee_per_gas: tx.max_fee_per_gas.unwrap().try_into().unwrap(), + max_priority_fee_per_gas: tx.max_priority_fee_per_gas.unwrap().try_into().unwrap(), + to: tx.to.into(), value: tx.value, - data: tx.data, access_list: tx.access_list.unwrap().into(), - }) - }; - EthereumTransaction { essence, signature } + blob_versioned_hashes: tx.blob_versioned_hashes.unwrap(), + max_fee_per_blob_gas: tx.max_fee_per_blob_gas.unwrap().try_into().unwrap(), + input: tx.data, + } + .into_signed(signature) + .into(), + v @ _ => panic!("invalid transaction type: {}", v.unwrap()), + } } } @@ -270,6 +280,26 @@ impl From for AccessList { } } +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TestWithdrawal { + pub address: Address, + pub amount: U64, + pub index: U64, + pub validator_index: U64, +} + +impl From for Withdrawal { + fn from(w: TestWithdrawal) -> Self { + Withdrawal { + address: w.address, + amount: w.amount.try_into().unwrap(), + index: w.index.try_into().unwrap(), + validator_index: w.validator_index.try_into().unwrap(), + } + } +} + /// Computes the Merkle proof for the given key in the trie. pub fn mpt_proof(root: &MptNode, key: impl AsRef<[u8]>) -> Result>, anyhow::Error> { let mut path = proof_internal(root, &trie::to_nibs(key.as_ref()))?; @@ -314,9 +344,9 @@ pub fn create_input( parent_state: TestState, header: Header, transactions: Vec, - withdrawals: Vec, + withdrawals: Vec, state: TestState, -) -> BlockBuildInput { +) -> BlockBuildInput { // create the provider DB let provider_db = ProviderDb::new( Box::new(TestProvider { @@ -327,12 +357,11 @@ pub fn create_input( parent_header.number, ); - let transactions: Vec = transactions - .into_iter() - .map(EthereumTransaction::from) - .collect(); + let transactions: Vec<_> = transactions.into_iter().map(TxEnvelope::from).collect(); + let withdrawals: Vec<_> = withdrawals.into_iter().map(Withdrawal::from).collect(); let input = BlockBuildInput { state_input: StateInput { + parent_header: parent_header.clone(), beneficiary: header.beneficiary, gas_limit: header.gas_limit, timestamp: header.timestamp, @@ -340,7 +369,7 @@ pub fn create_input( mix_hash: header.mix_hash, transactions: transactions.clone(), withdrawals: withdrawals.clone(), - parent_header: parent_header.clone(), + parent_beacon_block_root: header.parent_beacon_block_root, }, parent_state_trie: Default::default(), parent_storage: Default::default(), diff --git a/testing/ef-tests/testdata b/testing/ef-tests/testdata index 9b6382b1..853b1e03 160000 --- a/testing/ef-tests/testdata +++ b/testing/ef-tests/testdata @@ -1 +1 @@ -Subproject commit 9b6382b122140b5479a4ff6152ccf1459440ddff +Subproject commit 853b1e03b1078d370614002851ba1ee9803d9fcf diff --git a/testing/ef-tests/testguest/Cargo.lock b/testing/ef-tests/testguest/Cargo.lock index 44055f37..6c55a1a4 100644 --- a/testing/ef-tests/testguest/Cargo.lock +++ b/testing/ef-tests/testguest/Cargo.lock @@ -50,11 +50,59 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-eips", + "alloy-primitives", + "alloy-rlp", +] + +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "serde", +] + +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-json-rpc", + "alloy-primitives", + "alloy-rpc-types", + "alloy-signer", + "async-trait", + "futures-utils-wasm", + "serde", + "thiserror", +] + [[package]] name = "alloy-primitives" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" +checksum = "600d34d8de81e23b6d909c094e23b3d357e01ca36b78a8c5424c501eedbe86f0" dependencies = [ "alloy-rlp", "bytes", @@ -78,6 +126,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ + "alloy-rlp-derive", "arrayvec", "bytes", ] @@ -93,16 +142,53 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/Wollac/alloy.git?branch=fix/encoding#991ebece6b68bd900e8369f92dbbc2bf12bd7b27" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + [[package]] name = "alloy-sol-macro" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" +checksum = "e86ec0a47740b20bc5613b8712d0d321d031c4efc58e9645af96085d5cccfc27" dependencies = [ "const-hex", "dunce", "heck", - "indexmap", + "indexmap 2.2.3", "proc-macro-error", "proc-macro2", "quote", @@ -113,9 +199,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" +checksum = "ad09ec5853fa700d12d778ad224dcdec636af424d29fad84fb9a2f16a5b0ef09" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -123,6 +209,21 @@ dependencies = [ "serde", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.79" @@ -170,7 +271,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "hashbrown 0.13.2", - "itertools", + "itertools 0.10.5", "num-traits", "zeroize", ] @@ -205,7 +306,7 @@ dependencies = [ "ark-std 0.4.0", "derivative", "digest 0.10.7", - "itertools", + "itertools 0.10.5", "num-bigint", "num-traits", "paste", @@ -403,9 +504,9 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" +checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", @@ -480,9 +581,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -579,9 +680,9 @@ dependencies = [ [[package]] name = "c-kzg" -version = "0.4.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d8c306be83ec04bf5f73710badd8edf56dea23f2f0d8b7f9fe4644d371c758" +checksum = "3130f3d8717cc02e668a896af24984d5d5d4e8bf12e278e982e0f1bd88a0f9af" dependencies = [ "blst", "cc", @@ -609,7 +710,11 @@ version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b" dependencies = [ + "android-tzdata", + "iana-time-zone", "num-traits", + "serde", + "windows-targets 0.52.0", ] [[package]] @@ -708,6 +813,41 @@ dependencies = [ "typenum", ] +[[package]] +name = "darling" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.48", +] + +[[package]] +name = "darling_macro" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.48", +] + [[package]] name = "dary_heap" version = "0.3.6" @@ -737,6 +877,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", + "serde", ] [[package]] @@ -796,6 +937,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + [[package]] name = "ecdsa" version = "0.16.9" @@ -1177,6 +1324,12 @@ dependencies = [ "slab", ] +[[package]] +name = "futures-utils-wasm" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" + [[package]] name = "fxhash" version = "0.2.1" @@ -1255,13 +1408,19 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 2.2.3", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.13.2" @@ -1399,6 +1558,35 @@ dependencies = [ "tokio-rustls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + [[package]] name = "idna" version = "0.5.0" @@ -1447,6 +1635,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + [[package]] name = "indexmap" version = "2.2.3" @@ -1455,6 +1654,7 @@ checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177" dependencies = [ "equivalent", "hashbrown 0.14.3", + "serde", ] [[package]] @@ -1481,6 +1681,15 @@ 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 = "itoa" version = "1.0.10" @@ -2033,7 +2242,7 @@ checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" dependencies = [ "bit-set", "bit-vec", - "bitflags 2.4.2", + "bitflags 2.5.0", "lazy_static", "num-traits", "rand", @@ -2186,12 +2395,13 @@ dependencies = [ [[package]] name = "revm" -version = "5.0.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266f86bdefa6dac07d92e2f5c37d7d183f2575b2f9e0ee9cba9402dfde912524" +checksum = "24fd3ed4b62dc61c647552d8b781811ae25ec74d23309055077e4dfb392444d2" dependencies = [ "auto_impl", "cfg-if", + "dyn-clone", "revm-interpreter", "revm-precompile", "serde", @@ -2200,9 +2410,9 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "2.1.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a80b516cc706630e604e2fd47c281501d2fb222712be4328921361388b7d2df" +checksum = "9f0a1818f8c876b0d71a0714217c34da7df8a42c0462750768779d55680e4554" dependencies = [ "revm-primitives", "serde", @@ -2210,9 +2420,9 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "4.0.0" +version = "5.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6912fafe7f70a264ec5895875ce2f2d0621a39263844280c9ee7f85e35bbb9e" +checksum = "7a9645a70f1df1e5bd7fa8718b9ba486fac9c3f0467aa6b58e7f590d5f6fd0f7" dependencies = [ "aurora-engine-modexp", "c-kzg", @@ -2227,16 +2437,17 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b3683a40f1e94e7389c8e81e5f26bb5d30875ed0b48ab07985ec32eb6d6c712" +checksum = "323ad597cf75ac9cb1d161be29fcc3562426f0278a1d04741697fca556e1ceea" dependencies = [ "alloy-primitives", "auto_impl", - "bitflags 2.4.2", + "bitflags 2.5.0", "bitvec", "c-kzg", "cfg-if", + "dyn-clone", "enumn", "hashbrown 0.14.3", "hex", @@ -2293,9 +2504,9 @@ dependencies = [ [[package]] name = "risc0-binfmt" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d263c6370d7714d2a634b6d88deb3871d0fad1f9486a9da6d48139c1ac85b26" +checksum = "2ae2939426c60756f910352184716a3538748208c9e11ade4a507db3b2757157" dependencies = [ "anyhow", "elf", @@ -2307,9 +2518,9 @@ dependencies = [ [[package]] name = "risc0-circuit-recursion" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9835069929a0e7b6b4b34e6a83f08aaa9d34b30023b9ccaf96ddbe20404eba" +checksum = "a43cade35f73ad81ba974fe1d5e1513331f87052af8377b26b00a838f39c6920" dependencies = [ "anyhow", "bytemuck", @@ -2321,9 +2532,9 @@ dependencies = [ [[package]] name = "risc0-circuit-rv32im" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb1caa759ab74d08779e062fcf98f5bd34397dfde572516a52369f0ec46db650" +checksum = "31440989146b342a7d37c15079c9568c69b7f988f3b789f422c7d4ed76526ddb" dependencies = [ "anyhow", "risc0-core", @@ -2334,19 +2545,37 @@ dependencies = [ [[package]] name = "risc0-core" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be79c89bcd18886b376073e3da22f8b7963247a42dce7b49cf3d09853f51641e" +checksum = "02e0cbd09d03c23b572b66cd96a56143adb22bf895aca89c1a153ccebedaa0b4" dependencies = [ "bytemuck", "rand_core", ] +[[package]] +name = "risc0-groth16" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1e9b8dae3f9c3862b6278b2812989a2f5a537975e5bd6a687f07cf1df68a36" +dependencies = [ + "anyhow", + "ark-bn254", + "ark-groth16", + "ark-serialize 0.4.2", + "hex", + "num-bigint", + "num-derive", + "num-traits", + "risc0-zkp", + "serde", +] + [[package]] name = "risc0-zkp" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e20a57e04840a5afadebb5d232546245f4fd8bd0e774bd69bf4bf25f8ab90c04" +checksum = "b96b035f744ecaaa7e9809c699bc85cf669cbab6f297f141d918e9b4c8098b79" dependencies = [ "anyhow", "blake2", @@ -2364,25 +2593,22 @@ dependencies = [ [[package]] name = "risc0-zkvm" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922588cb4b884b3951316a65581ccdfd1174af93c54093190878366812073329" +checksum = "2a1275834c86176efc122a172c2b5f271a8a5d792de7efbc47dfbecaaaff9432" dependencies = [ "anyhow", - "ark-bn254", - "ark-groth16", - "ark-serialize 0.4.2", "bytemuck", "cfg-if", "getrandom", "hex", - "num-bigint", "num-derive", "num-traits", "risc0-binfmt", "risc0-circuit-recursion", "risc0-circuit-rv32im", "risc0-core", + "risc0-groth16", "risc0-zkp", "risc0-zkvm-platform", "rrs-lib", @@ -2394,9 +2620,9 @@ dependencies = [ [[package]] name = "risc0-zkvm-platform" -version = "0.20.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc5819c0c3bfd8f20b1226c9d4ca1f342eb3d8385e71211a9383a879643d1dde" +checksum = "03b6378c9e407be18a1560ed030fd87fb6056293c56263efac46c507ae97e0d7" dependencies = [ "bytemuck", "getrandom", @@ -2507,7 +2733,7 @@ version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -2629,6 +2855,7 @@ version = "0.28.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10" dependencies = [ + "rand", "secp256k1-sys", ] @@ -2703,7 +2930,7 @@ version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap", + "indexmap 2.2.3", "itoa", "ryu", "serde", @@ -2721,6 +2948,36 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee80b0e361bbf88fd2f6e242ccd19cfda072cb0faa6ae694ecee08199938569a" +dependencies = [ + "base64 0.21.7", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.2.3", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6561dc161a9224638a31d876ccdfefbc1df91d3f3a8342eddb35f055d48c7655" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "sha1" version = "0.10.6" @@ -2734,8 +2991,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" -source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2-v0.10.6-risczero.0#7fd6900c4f637bd15ee2642dfa77110f8f1ad065" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", @@ -2846,6 +3104,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strum" version = "0.25.0" @@ -2911,9 +3175,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" +checksum = "cb3d0961cd53c23ea94eeec56ba940f636f6394788976e9f16ca5ee0aca7464a" dependencies = [ "paste", "proc-macro2", @@ -3139,7 +3403,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3150,7 +3414,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3161,7 +3425,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap", + "indexmap 2.2.3", "toml_datetime", "winnow", ] @@ -3476,6 +3740,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.0", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -3717,6 +3990,7 @@ dependencies = [ "ruint", "serde", "serde_json", + "serde_with", "thiserror", "tokio", "zeth-primitives", @@ -3726,18 +4000,25 @@ dependencies = [ name = "zeth-primitives" version = "0.1.0" dependencies = [ + "alloy-consensus", + "alloy-eips", + "alloy-network", "alloy-primitives", "alloy-rlp", "alloy-rlp-derive", "anyhow", "bytes", "ethers-core", - "k256", "log", - "revm-primitives", "rlp", "serde", + "serde_with", "sha2", "sha3", "thiserror", ] + +[[patch.unused]] +name = "sha2" +version = "0.10.6" +source = "git+https://github.com/risc0/RustCrypto-hashes?tag=sha2-v0.10.6-risczero.0#7fd6900c4f637bd15ee2642dfa77110f8f1ad065" diff --git a/testing/ef-tests/testguest/Cargo.toml b/testing/ef-tests/testguest/Cargo.toml index 2362fb20..8dc2cc65 100644 --- a/testing/ef-tests/testguest/Cargo.toml +++ b/testing/ef-tests/testguest/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" [workspace] [dependencies] -risc0-zkvm = { version = "0.20.1", default-features = false, features = ['std'] } +risc0-zkvm = { version = "0.21.0", default-features = false, features = ['std'] } zeth-lib = { path = "../../../lib", default-features = false } [patch.crates-io] diff --git a/testing/ef-tests/tests/evm.rs b/testing/ef-tests/tests/evm.rs index 9d68a475..b17bae24 100644 --- a/testing/ef-tests/tests/evm.rs +++ b/testing/ef-tests/tests/evm.rs @@ -21,7 +21,7 @@ use zeth_lib::{ builder::{BlockBuilderStrategy, EthereumStrategy}, output::BlockBuildOutput, }; -use zeth_primitives::{block::Header, trie::StateAccount}; +use zeth_primitives::{trie::StateAccount, Header}; use zeth_testeth::{ create_input, ethers, ethtests::{read_eth_test, EthTestCase}, @@ -35,29 +35,35 @@ fn evm( path: PathBuf, ) { let _ = env_logger::builder() - .filter_level(log::LevelFilter::Debug) + .filter_level(log::LevelFilter::Trace) .is_test(true) .try_init(); for EthTestCase { + name, mut json, genesis, chain_spec, } in read_eth_test(path) { // only one block supported for now - assert_eq!(json.blocks.len(), 1); + if json.blocks.len() > 1 { + println!("skipping '{}': more than one block", name); + continue; + } let block = json.blocks.pop().unwrap(); // skip failing tests for now if let Some(message) = block.expect_exception { - println!("skipping ({})", message); - break; + println!("skipping '{}': {}", name, message); + continue; } + println!("running '{}'", name); + let block_header = block.block_header.unwrap(); let expected_header: Header = block_header.clone().into(); - assert_eq!(&expected_header.hash(), &block_header.hash); + assert_eq!(&expected_header.hash_slow(), &block_header.hash); // using the empty/default state for the input prepares all accounts for deletion // this leads to larger input, but can never fail @@ -69,7 +75,7 @@ fn evm( json.pre, expected_header.clone(), block.transactions, - block.withdrawals.unwrap_or_default(), + block.withdrawals, post_state, ); let input_state_input_hash = input.state_input.hash(); @@ -105,7 +111,7 @@ fn evm( // the headers should match assert_eq!(new_block_head, expected_header); - assert_eq!(new_block_hash, expected_header.hash()); + assert_eq!(new_block_hash, expected_header.hash_slow()); assert_eq!(input_state_input_hash, state_input_hash); } } diff --git a/testing/ef-tests/tests/executor.rs b/testing/ef-tests/tests/executor.rs index a9b8bb9d..a04d6a42 100644 --- a/testing/ef-tests/tests/executor.rs +++ b/testing/ef-tests/tests/executor.rs @@ -16,11 +16,10 @@ use std::path::PathBuf; -use risc0_zkvm::{ExecutorEnv, ExecutorImpl, FileSegmentRef}; +use risc0_zkvm::{ExecutorEnv, ExecutorImpl}; use rstest::rstest; -use tempfile::tempdir; use zeth_lib::output::BlockBuildOutput; -use zeth_primitives::block::Header; +use zeth_primitives::Header; use zeth_testeth::{ create_input, ethtests::{read_eth_test, EthTestCase}, @@ -42,6 +41,7 @@ fn executor( .try_init(); for EthTestCase { + name, json, genesis, chain_spec, @@ -57,9 +57,11 @@ fn executor( break; } + println!("running '{}'", name); + let block_header = block.block_header.unwrap(); let expected_header: Header = block_header.clone().into(); - assert_eq!(&expected_header.hash(), &block_header.hash); + assert_eq!(&expected_header.hash_slow(), &block_header.hash); let input = create_input( &chain_spec, @@ -67,7 +69,7 @@ fn executor( json.pre, expected_header.clone(), block.transactions, - block.withdrawals.unwrap_or_default(), + block.withdrawals, json.post.unwrap(), ); @@ -80,14 +82,9 @@ fn executor( .unwrap() .build() .unwrap(); - let mut exec = ExecutorImpl::from_elf(env, TEST_GUEST_ELF).unwrap(); - let segment_dir = tempdir().unwrap(); - let session = exec - .run_with_callback(|segment| { - Ok(Box::new(FileSegmentRef::new(&segment, segment_dir.path())?)) - }) - .unwrap(); + let mut exec = ExecutorImpl::from_elf(env, TEST_GUEST_ELF).unwrap(); + let session = exec.run().unwrap(); println!("Generated {} segments", session.segments.len()); let build_output: BlockBuildOutput = session.journal.unwrap().decode().unwrap(); @@ -99,6 +96,6 @@ fn executor( panic!("Block build failed!") }; println!("Block hash (from executor): {}", new_block_hash); - assert_eq!(new_block_hash, expected_header.hash()); + assert_eq!(new_block_hash, expected_header.hash_slow()); } }