diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5930db66..d42b8e5d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: crate: cargo-binstall - run: cargo binstall -y --force cargo-risczero@${{ env.RISC0_VERSION }} - run: cargo risczero install --version $RISC0_TOOLCHAIN_VERSION - - run: cargo test --workspace --all-targets -F ef-tests + - run: cargo test --workspace --all-targets -F ef-tests,debug-guest-build clippy: name: clippy diff --git a/.gitignore b/.gitignore index dcb9cd8c..f6d7eb7a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,10 @@ .DS_Store target/ tmp/ -rpc_cache/ +cache_rpc/ +cache_zkp/ log.txt *.pb *.zkp -rpc_cache.json +cache_rpc.json .idea diff --git a/Cargo.lock b/Cargo.lock index 6a745cc9..9bf29764 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,9 +69,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "alloy-primitives" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3729132072f369bc4e8e6e070f9cf4deb3490fc9b9eea6f71f75ec19406df811" +checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" dependencies = [ "alloy-rlp", "bytes", @@ -112,14 +112,14 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5531f0a16e36c547e68c73a1638bea1f26237ee8ae785527190c4e4f9fecd2c5" +checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" dependencies = [ "const-hex", "dunce", "heck", - "indexmap 2.1.0", + "indexmap 2.2.1", "proc-macro-error", "proc-macro2", "quote", @@ -130,9 +130,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783eb720b73d38f9d4c1fb9890e4db6bc8c708f7aa77d3071a19e06091ecd1c9" +checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -171,9 +171,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "2faccea4cc4ab4a667ce676a30e8ec13922a692c99bb8f5b11f1502c72e04220" [[package]] name = "anstyle-parse" @@ -209,6 +209,15 @@ version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "ark-bn254" version = "0.4.0" @@ -498,14 +507,13 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -673,17 +681,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "bonsai-sdk" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "441d1092e11977985946b6564251df91d80ae36982128e53be52a32548ad8762" -dependencies = [ - "reqwest", - "serde", - "thiserror", -] - [[package]] name = "bonsai-sdk" version = "0.6.0" @@ -693,6 +690,7 @@ dependencies = [ "reqwest", "serde", "thiserror", + "tokio", ] [[package]] @@ -720,9 +718,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" dependencies = [ "bytemuck_derive", ] @@ -827,9 +825,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", @@ -1036,11 +1034,57 @@ dependencies = [ "typenum", ] +[[package]] +name = "cust" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6cc71911e179f12483b9734120b45bd00bf64fab085cc4818428523eedd469" +dependencies = [ + "bitflags 1.3.2", + "bytemuck", + "cust_core", + "cust_derive", + "cust_raw", + "find_cuda_helper", +] + +[[package]] +name = "cust_core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039f79662cb8f890cbf335e818cd522d6e3a53fe63f61d1aaaf859cd3d975f06" +dependencies = [ + "cust_derive", + "glam", + "mint", + "vek", +] + +[[package]] +name = "cust_derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3bc95fe629aed92b2423de6ccff9e40174b21d19cb6ee6281a4d04ac72f66" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cust_raw" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf40d6ade12cb9828bbc844b9875c7b93d25e67a3c9bf61c7aa3ae09e402bf8" +dependencies = [ + "find_cuda_helper", +] + [[package]] name = "darling" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "da01daa5f6d41c91358398e8db4dde38e292378da1f28300b59ef4732b879454" dependencies = [ "darling_core", "darling_macro", @@ -1048,9 +1092,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "f44f6238b948a3c6c3073cdf53bb0c2d5e024ee27e0f35bfe9d556a12395808a" dependencies = [ "fnv", "ident_case", @@ -1062,9 +1106,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "0d2d88bd93979b1feb760a6b5c531ac5ba06bd63e74894c377af02faee07b9cd" dependencies = [ "darling_core", "quote", @@ -1505,6 +1549,15 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "find_cuda_helper" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f9e65c593dd01ac77daad909ea4ad17f0d6d1776193fc8ea766356177abdad" +dependencies = [ + "glob", +] + [[package]] name = "fixed-hash" version = "0.8.0" @@ -1539,15 +1592,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared 0.1.1", -] - [[package]] name = "foreign-types" version = "0.5.0" @@ -1555,7 +1599,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared 0.3.1", + "foreign-types-shared", ] [[package]] @@ -1569,12 +1613,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -1736,6 +1774,15 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "glam" +version = "0.20.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43e957e744be03f5801a55472f593d43fabdebf25a4585db250f04d86b1675f" +dependencies = [ + "num-traits", +] + [[package]] name = "glob" version = "0.3.1" @@ -1777,7 +1824,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.1", "slab", "tokio", "tokio-util", @@ -1948,19 +1995,6 @@ dependencies = [ "tokio-rustls", ] -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper", - "native-tls", - "tokio", - "tokio-native-tls", -] - [[package]] name = "iana-time-zone" version = "0.1.59" @@ -2051,9 +2085,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -2071,9 +2105,9 @@ dependencies = [ [[package]] name = "inventory" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8573b2b1fb643a372c73b23f4da5f888677feef3305146d68a539250a9bccc7" +checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" [[package]] name = "ipnet" @@ -2341,7 +2375,7 @@ dependencies = [ "bitflags 1.3.2", "block", "core-graphics-types", - "foreign-types 0.5.0", + "foreign-types", "log", "objc", "paste", @@ -2368,6 +2402,12 @@ dependencies = [ "adler", ] +[[package]] +name = "mint" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e53debba6bda7a793e5f99b8dacf19e626084f525f7829104ba9898f367d85ff" + [[package]] name = "mio" version = "0.8.10" @@ -2385,24 +2425,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a" -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "ndarray" version = "0.15.6" @@ -2618,50 +2640,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "openssl" -version = "0.10.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15c9d69dd87a29568d4d017cfe8ec518706046a05184e5aea92d0af890b803c8" -dependencies = [ - "bitflags 2.4.2", - "cfg-if", - "foreign-types 0.3.2", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.48", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22e1bf214306098e4832460f797824c05d25aacdf896f64a985fb0fd992454ae" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "option-ext" version = "0.2.0" @@ -2762,7 +2740,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.1.0", + "indexmap 2.2.1", ] [[package]] @@ -2777,18 +2755,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", @@ -2817,12 +2795,6 @@ dependencies = [ "spki", ] -[[package]] -name = "pkg-config" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb" - [[package]] name = "powerfmt" version = "0.2.0" @@ -3150,9 +3122,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -3187,12 +3159,10 @@ dependencies = [ "http-body", "hyper", "hyper-rustls", - "hyper-tls", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -3203,7 +3173,6 @@ dependencies = [ "serde_urlencoded", "system-configuration", "tokio", - "tokio-native-tls", "tokio-rustls", "tower-service", "url", @@ -3368,6 +3337,7 @@ checksum = "404ed28b36b5e5a346267870e675ec634678193c111376334d0e00edcecefece" dependencies = [ "anyhow", "bytemuck", + "cust", "downloader", "hex", "metal", @@ -3399,6 +3369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc4890f3c85bfbefdc05f926778d92d1fa24b8d931a077170e07c3b6e14e4c29" dependencies = [ "anyhow", + "cust", "metal", "rand", "rayon", @@ -3430,6 +3401,16 @@ dependencies = [ "rand_core", ] +[[package]] +name = "risc0-sppark" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5be1d1ff7fe501c9f420654bc1ff7461909b85e7f8fb3698a8812c0a8a787306" +dependencies = [ + "cc", + "which", +] + [[package]] name = "risc0-sys" version = "0.20.0" @@ -3437,7 +3418,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "510fcce109b5d5df9458f2ce578504f97fc786b1330cc2130ea12824ff286ef7" dependencies = [ "cc", + "cust", "risc0-build-kernel", + "risc0-sppark", ] [[package]] @@ -3449,6 +3432,7 @@ dependencies = [ "anyhow", "blake2", "bytemuck", + "cust", "digest 0.10.7", "ff", "hex", @@ -3479,7 +3463,7 @@ dependencies = [ "ark-groth16", "ark-serialize 0.4.2", "bincode", - "bonsai-sdk 0.6.0", + "bonsai-sdk", "bytemuck", "bytes", "cfg-if", @@ -3759,15 +3743,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scopeguard" version = "1.2.0" @@ -3816,29 +3791,6 @@ dependencies = [ "cc", ] -[[package]] -name = "security-framework" -version = "2.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "semver" version = "0.11.0" @@ -3880,18 +3832,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", @@ -3900,11 +3852,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "itoa", "ryu", "serde", @@ -3924,15 +3876,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58c3a1b3e418f61c25b2aeb43fc6c95eaa252b8cecdda67f401943e9e08d33f" +checksum = "f5c9fdb6b00a489875b22efd4b78fe2b363b72265cc5f6eb2e2b9ee270e6140c" dependencies = [ "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.1.0", + "indexmap 2.2.1", "serde", "serde_json", "serde_with_macros", @@ -3941,9 +3893,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2068b437a31fc68f25dd7edc296b078f04b45145c199d8eed9866e45f1ff274" +checksum = "dbff351eb4b33600a2e138dfa0b10b65a238ea8ff8fb2387c422c5022a3e8298" dependencies = [ "darling", "proc-macro2", @@ -4160,9 +4112,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cfbd642e1748fd9e47951973abfa78f825b11fbf68af9e6b9db4c983a770166" +checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" dependencies = [ "paste", "proc-macro2", @@ -4337,16 +4289,6 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.24.1" @@ -4398,7 +4340,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -4409,7 +4351,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -4420,7 +4362,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -4642,10 +4584,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" [[package]] -name = "vcpkg" -version = "0.2.15" +name = "vek" +version = "0.15.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "8085882662f9bc47fc8b0cdafa5e19df8f592f650c02b9083da8d45ac9eebd17" +dependencies = [ + "approx", + "num-integer", + "num-traits", + "rustc_version 0.4.0", +] [[package]] name = "version_check" @@ -4945,9 +4893,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.34" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] @@ -5038,7 +4986,7 @@ dependencies = [ "anyhow", "assert_cmd", "bincode", - "bonsai-sdk 0.5.1", + "bonsai-sdk", "bytemuck", "clap", "env_logger", @@ -5052,6 +5000,7 @@ dependencies = [ "serde", "tempfile", "tokio", + "tracing", "zeth-guests", "zeth-lib", "zeth-primitives", @@ -5068,6 +5017,9 @@ dependencies = [ name = "zeth-lib" version = "0.1.0" dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-rlp-derive", "alloy-sol-types", "anyhow", "bincode", @@ -5104,6 +5056,7 @@ dependencies = [ "ethers-core", "hex-literal", "k256", + "log", "revm-primitives", "rlp", "serde", diff --git a/Cargo.toml b/Cargo.toml index 3c7bcc79..83845e2c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ lto = true opt-level = 3 [workspace.dependencies] -bonsai-sdk = "0.5" +bonsai-sdk = { version = "0.6.0", features = ["async"] } hashbrown = { version = "0.14.3", features = ["inline-more"] } risc0-build = { version = "0.20.0" } risc0-zkvm = { version = "0.20.0", default-features = false } diff --git a/README.md b/README.md index ef749e9b..4df78434 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,8 @@ # zeth -**NEW: Zeth now supports Optimism blocks! Just pass in `--network=optimism`!** +Zeth is an open-source ZK block prover for Ethereum and Optimism built on the RISC Zero zkVM. -Zeth is an open-source ZK block prover for Ethereum built on the RISC Zero zkVM. - -Zeth makes it possible to *prove* that a given Ethereum block is valid +Zeth makes it possible to *prove* that a given block is valid (i.e., is the result of applying the given list of transactions to the parent block) *without* relying on the validator or sync committees. This is because Zeth does *all* the work needed to construct a new block *from within the zkVM*, including: @@ -18,6 +16,8 @@ This is because Zeth does *all* the work needed to construct a new block *from w After constructing the new block, Zeth calculates and outputs the block hash. By running this process within the zkVM, we obtain a ZK proof that the new block is valid. +For Optimism, our validity proof ensures that the block is correctly derived from the +available data posted to Ethereum. ## Status @@ -25,139 +25,322 @@ Zeth is experimental and may still contain bugs. ## Usage -### Building +### Prerequisites + +Zeth primarily requires the availability of Ethereum/Optimism RPC provider(s) data. +Two complementary types of providers are supported: + +* RPC provider. + This fetches data from a Web2 RPC provider, such as [Alchemy](https://www.alchemy.com/). + Specified using the `--eth-rpc-url=` and `--op-rpc-url=` parameters. +* Cached RPC provider. + This fetches RPC data from a local file when possible, and falls back to a Web2 RPC provider when necessary. + It amends the local file with results from the Web2 provider so that subsequent runs don't require additional Web2 RPC calls. + Specified using the `--cache[=]` parameter. + +### Installation + + +#### RISC Zero zkVM -- Install the `cargo risczero` tool and the `risc0` toolchain: +Install the `cargo risczero` tool and the `risc0` toolchain: ```console -$ cargo install cargo-risczero -$ cargo risczero install +cargo install cargo-risczero +cargo risczero install ``` -- Clone the repository and build with `cargo`: +#### zeth +Clone the repository and build with `cargo` using one of the following commands: + +* CPU Proving (slow): +```console +cargo build --release +``` + +- GPU Proving (apple/metal) ```console -$ cargo build --release +cargo build -F metal --release ``` -### Running +- GPU Proving (nvidia/cuda) +```console +cargo build -F cuda --release +``` +#### Execution: -Zeth currently has several modes of execution: +Run the built binary (instead of using `cargo run`) using: +```console +RUST_LOG=info ./target/release/zeth ``` -Usage: zeth [OPTIONS] --block-no= + +### CLI + +Zeth currently has four main modes of execution: + +```console +RUST_LOG=info ./target/release/zeth help +``` +```console +Usage: zeth + +Commands: + build Build blocks natively outside the zkVM + run Run the block creation process inside the executor + prove Provably create blocks inside the zkVM + verify Verify a block creation receipt + op-info Output debug information about an optimism block + help Print this message or the help of the given subcommand(s) Options: - -r, --rpc-url= - URL of the chain RPC node. - -c, --cache[=] - Use a local directory as a cache for RPC calls. - Accepts a custom directory. - [default: host/testdata] - -n, --network= - Network name (ethereum/optimism). - [default: ethereum] - -b, --block-no= - Block number to validate. - -l, --local-exec[=] - Runs the verification inside the zkvm executor locally. - Accepts a custom maximum segment cycle count as a power of 2. [default: 20] - -s, --submit-to-bonsai - Whether to submit the proving workload to Bonsai. - -v, --verify-bonsai-receipt-uuid= - Bonsai Session UUID to use for receipt verification. - -p, --profile - Whether to profile the zkVM execution. - -h, --help - Print help. - -V, --version - Print version. + -h, --help Print help + -V, --version Print version +``` +For every command, the `--network` parameter can be set to either `ethereum` or `optimism` for provable construction +of single blocks from either chain on its own. +To provably derive Optimism blocks using the data posted on the Ethereum chain, use `--network=optimism-derived`, +but `optimism-derived` is not supported by the `run` and `op-info` commands. + +#### build +*This command only natively builds blocks and does not generate any proofs.* +```console +RUST_LOG=info ./target/release/zeth build --help ``` -Zeth primarily requires an Ethereum RPC provider. -Two complementary types of providers are supported: +```console +Build blocks natively outside the zkVM -* RPC provider. - This fetches data from a Web2 RPC provider, such as [Alchemy](https://www.alchemy.com/). - Specified using the `--rpc-url=` parameter. -* Cached RPC provider. - This fetches RPC data from a local file when possible, and falls back to a Web2 RPC provider when necessary. - It amends the local file with results from the Web2 provider so that subsequent runs don't require additional Web2 RPC calls. - Specified using the `--cache[=CACHE_DIRECTORY]` parameter. +Usage: zeth build [OPTIONS] --block-number= + +Options: + -w, --network= Network name (ethereum/optimism/optimism-derived) [default: ethereum] + -e, --eth-rpc-url= URL of the Ethereum RPC node + -o, --op-rpc-url= URL of the Optimism RPC node + -c, --cache[=] Use a local directory as a cache for RPC calls. Accepts a custom directory. [default: cache_rpc] + -b, --block-number= Block number to begin from + -n, --block-count= Number of blocks to provably derive [default: 1] + -m, --composition[=] Compose separate block derivation proofs together. Accepts a custom number of blocks to process per derivation call. (optimism-derived network only) [default: 1] + -h, --help Print help +``` -**Quick test mode**. -This is the default. When run in this mode, Zeth does all the work needed to construct an Ethereum block and verifies the correctness of the result using the RPC provider. No proofs are generated. -You can omit the `rpc-url` parameter if you do not change the `block-no` parameters from the below examples as the data is already cached. -Ethereum: +With `--network=optimism-derived`, the derivation proof creation is done without proof composition by default, +requiring the derivation to be carried out inside a single zkVM execution. + +**Examples** +The `host/testdata` and `host/testdata/derivation` directories come preloaded with a few cache files that you can use +out of the box without the need to explicitly specify an RPC URL: ```console -$ RUST_LOG=info ./target/release/zeth \ - --rpc-url="https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY" \ - --cache \ - --block-no=16424130 +RUST_LOG=info ./target/release/zeth build \ + --network=ethereum \ + --cache=host/testdata \ + --block-number=16424130 ``` -Optimism: ```console -$ RUST_LOG=info ./target/release/zeth \ - --network=optimism \ - --rpc-url="https://opt-mainnet.g.alchemy.com/v2/YOUR_API_KEY" \ - --cache \ - --block-no=107728767 +RUST_LOG=info ./target/release/zeth build \ + --network=optimism \ + --cache=host/testdata \ + --block-number=107728767 +``` +```console +RUST_LOG=info ./target/release/zeth build \ + --network=optimism-derived \ + --cache=host/testdata/derivation \ + --block-number=109279674 \ + --block-count=4 +``` +**Composition** The optimism derivation proof (`--network=optimism-derived`) can alternatively be created using proof composition by +setting the `--composition` parameter to the number of op blocks per rolled up proof. +In the following example, 2 derivation proofs of 2 sequential blocks each are composed to obtain the final derivation +proof for the 4 sequential blocks: +```console +RUST_LOG=info ./target/release/zeth build \ + --network=optimism-derived \ + --cache=host/testdata/derivation \ + --block-number=109279674 \ + --block-count=4 \ + --composition=2 +``` + +#### run +*This command only invokes the RISC-V emulator and does not generate any proofs.* +```console +RUST_LOG=info ./target/release/zeth run --help +``` +```console +Run the block creation process inside the executor + +Usage: zeth run [OPTIONS] --block-number= + +Options: + -w, --network= Network name (ethereum/optimism/optimism-derived) [default: ethereum] + -e, --eth-rpc-url= URL of the Ethereum RPC node + -o, --op-rpc-url= URL of the Optimism RPC node + -c, --cache[=] Use a local directory as a cache for RPC calls. Accepts a custom directory. [default: cache_rpc] + -b, --block-number= Block number to begin from + -n, --block-count= Number of blocks to provably derive [default: 1] + -x, --execution-po2= The maximum segment cycle count as a power of 2 [default: 20] + -p, --profile Whether to profile the zkVM execution + -h, --help Print help ``` **Local executor mode**. -To run in this mode, add the parameter `--local-exec[=SEGMENT_LIMIT]`. When run in this mode, Zeth does all the work needed to construct an Ethereum block from within the zkVM's non-proving emulator. Correctness of the result is checked using the RPC provider. This is useful for measuring the size of the computation (number of execution segments and cycles). No proofs are generated. +**Examples** +The below examples will invoke the executor, which will take a bit more time, and output the number of cycles required +for execution/proving inside the zkVM: +```console +RUST_LOG=info ./target/release/zeth run \ + --cache=host/testdata \ + --network=ethereum \ + --block-number=16424130 +``` +```console +RUST_LOG=info ./target/release/zeth run \ + --cache=host/testdata \ + --network=optimism \ + --block-number=107728767 +``` + +The `run` command does not support proof composition (required by `--network=optimism-derived`) because receipts are required for this process inside the +executor. +Alternatively, one can call the `prove` command in dev mode (`RISC0_DEV_MODE=true`) for the same functionality, as +demonstrated in the next section. + +#### prove +*This command generates a ZK proof, unless dev mode is enabled through the environment variable `RISC0_DEV_MODE=true`.* ```console -$ RUST_LOG=info ./target/release/zeth \ - --rpc-url="https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY" \ - --cache \ - --block-no=16424130 \ - --local-exec +RUST_LOG=info ./target/release/zeth prove --help ``` +```console +Provably create blocks inside the zkVM + +Usage: zeth prove [OPTIONS] --block-number= -**Bonsai proving mode**. -*This mode generates a ZK proof.* +Options: + -w, --network= Network name (ethereum/optimism/optimism-derived) [default: ethereum] + -e, --eth-rpc-url= URL of the Ethereum RPC node + -o, --op-rpc-url= URL of the Optimism RPC node + -c, --cache[=] Use a local directory as a cache for RPC calls. Accepts a custom directory. [default: cache_rpc] + -b, --block-number= Block number to begin from + -n, --block-count= Number of blocks to provably derive [default: 1] + -x, --execution-po2= The maximum segment cycle count as a power of 2 [default: 20] + -p, --profile Whether to profile the zkVM execution + -m, --composition[=] Compose separate block derivation proofs together. Accepts a custom number of blocks to process per derivation call. (optimism-derived network only) [default: 1] + -s, --submit-to-bonsai Prove remotely using Bonsai + -h, --help Print help +``` + +**Proving on Bonsai**. To run in this mode, add the parameter `--submit-to-bonsai`. When run in this mode, Zeth submits a proving task to the [Bonsai proving service](https://www.bonsai.xyz/), -which then constructs an Ethereum block entirely from within the zkVM. -This mode checks the correctness of the result using the RPC provider. +which then constructs the blocks entirely from within the zkVM. +This mode checks the correctness of the result on your machine using the RPC provider(s). It also outputs the Bonsai session UUID, and polls Bonsai until the proof is complete. -To use this feature, first set the `BONSAI_API_URL` and `BONSAI_API_KEY` environment variables, -then follow the instructions below for submitting jobs to Bonsai and verifying the proofs. +To use this feature, first set the `BONSAI_API_URL` and `BONSAI_API_KEY` environment variables before executing zeth +to submit jobs to Bonsai. Need a Bonsai API key? [Sign up today](https://bonsai.xyz/apply). +**Examples** +The below examples will invoke the prover, which will take a potentially significant time to generate a ZK proof +locally: +```console +RUST_LOG=info ./target/release/zeth prove \ + --cache=host/testdata \ + --network=ethereum \ + --block-number=16424130 +``` ```console -$ RUST_LOG=info ./target/release/zeth \ - --rpc-url="https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY" \ - --cache \ - --block-no=16424130 \ - --submit-to-bonsai +RUST_LOG=info ./target/release/zeth prove \ + --cache=host/testdata \ + --network=optimism \ + --block-number=107728767 ``` +```console +RUST_LOG=info ./target/release/zeth prove \ + --network=optimism-derived \ + --cache=host/testdata/derivation \ + --block-number=109279674 \ + --block-count=4 +``` +**Composition** Alternatively, we can run composition in dev mode, which should only as much time as required by the +executor, using the following command: +```console +RISC0_DEV_MODE=true RUST_LOG=info ./target/release/zeth prove \ + --network=optimism-derived \ + --cache=host/testdata/derivation \ + --block-number=109279674 \ + --block-count=4 \ + --composition=2 +``` +***NOTE*** Proving in dev mode only generates dummy receipts that do not attest to the validity of the computation and +are not verifiable outside of dev mode! -**Bonsai verify mode**. -*This mode verifies the ZK proof.* -To run in this mode, add the parameter `--verify-bonsai-receipt-uuid=BONSAI_SESSION_UUID`, -where `BONSAI_SESSION_UUID` is the session UUID returned by the `--submit-to-bonsai` mode. -This mode checks the correctness of the result using the RPC provider. +#### verify +*This command verifies a ZK proof generated on Bonsai.* +``` +RUST_LOG=info ./target/release/zeth verify --help +``` +``` +Verify a block creation receipt -```console -$ RUST_LOG=info ./target/release/zeth \ - --rpc-url="https://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY" \ - --cache \ - --block-no=16424130 \ - --verify-bonsai-receipt-uuid=BONSAI_SESSION_UUID +Usage: zeth verify [OPTIONS] --block-number= --bonsai-receipt-uuid= + +Options: + -w, --network= + Network name (ethereum/optimism/optimism-derived) [default: ethereum] + -e, --eth-rpc-url= + URL of the Ethereum RPC node + -o, --op-rpc-url= + URL of the Optimism RPC node + -c, --cache[=] + Use a local directory as a cache for RPC calls. Accepts a custom directory. [default: cache_rpc] + -b, --block-number= + Block number to begin from + -n, --block-count= + Number of blocks to provably derive [default: 1] + -b, --bonsai-receipt-uuid= + Verify the receipt from the provided Bonsai Session UUID + -h, --help + Print help +``` + +This command first natively builds the specified block(s), and then validates the correctness of the receipt generated +on Bonsai specified by the `--bonsai-receipt-uuid=BONSAI_SESSION_UUID` parameter, where `BONSAI_SESSION_UUID` is the +session UUID returned when proving using `--submit-to-bonsai`. + +#### op-info +``` +RUST_LOG=info ./target/release/zeth op-info --help +``` ``` +Output debug information about an optimism block + +Usage: zeth op-info [OPTIONS] --block-number= + +Options: + -w, --network= Network name (ethereum/optimism/optimism-derived) [default: ethereum] + -e, --eth-rpc-url= URL of the Ethereum RPC node + -o, --op-rpc-url= URL of the Optimism RPC node + -c, --cache[=] Use a local directory as a cache for RPC calls. Accepts a custom directory. [default: cache_rpc] + -b, --block-number= Block number to begin from + -n, --block-count= Number of blocks to provably derive [default: 1] + -h, --help Print help +``` +This command only outputs debug information for development use. + ## Additional resources diff --git a/guests/Cargo.toml b/guests/Cargo.toml index 999c3534..11ef6ee9 100644 --- a/guests/Cargo.toml +++ b/guests/Cargo.toml @@ -8,3 +8,9 @@ risc0-build = { workspace = true } [package.metadata.risc0] methods = ["eth-block", "op-block", "op-derive", "op-compose"] + +[features] +debug-guest-build = [] +default = [ + "risc0-build/docker" +] \ No newline at end of file diff --git a/guests/build.rs b/guests/build.rs index 42c6db8e..29578ad4 100644 --- a/guests/build.rs +++ b/guests/build.rs @@ -12,6 +12,29 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(not(feature = "debug-guest-build"))] fn main() { - risc0_build::embed_methods(); + let cwd = std::env::current_dir().unwrap(); + let root_dir = cwd.parent().map(|d| d.to_path_buf()); + let build_opts = std::collections::HashMap::from_iter( + ["eth-block", "op-block", "op-derive", "op-compose"] + .into_iter() + .map(|guest_pkg| { + ( + guest_pkg, + risc0_build::GuestOptions { + features: vec![], + use_docker: Some(risc0_build::DockerOptions { + root_dir: root_dir.clone(), + }), + }, + ) + }), + ); + risc0_build::embed_methods_with_options(build_opts); +} + +#[cfg(feature = "debug-guest-build")] +fn main() { + risc0_build::embed_methods() } diff --git a/guests/eth-block/Cargo.lock b/guests/eth-block/Cargo.lock index 16203605..664c86c7 100644 --- a/guests/eth-block/Cargo.lock +++ b/guests/eth-block/Cargo.lock @@ -52,9 +52,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "alloy-primitives" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3729132072f369bc4e8e6e070f9cf4deb3490fc9b9eea6f71f75ec19406df811" +checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" dependencies = [ "alloy-rlp", "bytes", @@ -95,9 +95,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5531f0a16e36c547e68c73a1638bea1f26237ee8ae785527190c4e4f9fecd2c5" +checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" dependencies = [ "const-hex", "dunce", @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783eb720b73d38f9d4c1fb9890e4db6bc8c708f7aa77d3071a19e06091ecd1c9" +checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -473,6 +473,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.66.1" @@ -583,9 +592,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" dependencies = [ "bytemuck_derive", ] @@ -657,9 +666,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", @@ -2098,18 +2107,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", @@ -2338,9 +2347,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -2932,9 +2941,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58c3a1b3e418f61c25b2aeb43fc6c95eaa252b8cecdda67f401943e9e08d33f" +checksum = "f5c9fdb6b00a489875b22efd4b78fe2b363b72265cc5f6eb2e2b9ee270e6140c" dependencies = [ "base64 0.21.7", "chrono", @@ -2949,9 +2958,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2068b437a31fc68f25dd7edc296b078f04b45145c199d8eed9866e45f1ff274" +checksum = "dbff351eb4b33600a2e138dfa0b10b65a238ea8ff8fb2387c422c5022a3e8298" dependencies = [ "darling", "proc-macro2", @@ -3161,9 +3170,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cfbd642e1748fd9e47951973abfa78f825b11fbf68af9e6b9db4c983a770166" +checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" dependencies = [ "paste", "proc-macro2", @@ -3955,8 +3964,12 @@ dependencies = [ name = "zeth-lib" version = "0.1.0" dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-rlp-derive", "alloy-sol-types", "anyhow", + "bincode", "bytes", "chrono", "ethers-core", @@ -3988,6 +4001,7 @@ dependencies = [ "bytes", "ethers-core", "k256", + "log", "revm-primitives", "rlp", "serde", diff --git a/guests/eth-block/src/main.rs b/guests/eth-block/src/main.rs index eccfe9d1..9a8564d7 100644 --- a/guests/eth-block/src/main.rs +++ b/guests/eth-block/src/main.rs @@ -26,10 +26,15 @@ pub fn main() { // Read the input previous block and transaction data let input = env::read(); // Build the resulting block - let (header, state) = EthereumStrategy::build_from(Ð_MAINNET_CHAIN_SPEC, input) + let mut output = EthereumStrategy::build_from(Ð_MAINNET_CHAIN_SPEC, input) .expect("Failed to build the resulting block"); - // Output the resulting block's hash to the journal - env::commit(&header.hash()); + // Abridge successful construction results + if let Some(replaced_state) = output.replace_state_with_hash() { + // Leak memory, save cycles + core::mem::forget(replaced_state); + } + // Output the construction result + env::commit(&output); // Leak memory, save cycles - core::mem::forget((header, state)); + core::mem::forget(output); } diff --git a/guests/op-block/Cargo.lock b/guests/op-block/Cargo.lock index c444c94f..23b9426b 100644 --- a/guests/op-block/Cargo.lock +++ b/guests/op-block/Cargo.lock @@ -52,9 +52,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "alloy-primitives" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3729132072f369bc4e8e6e070f9cf4deb3490fc9b9eea6f71f75ec19406df811" +checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" dependencies = [ "alloy-rlp", "bytes", @@ -95,14 +95,14 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5531f0a16e36c547e68c73a1638bea1f26237ee8ae785527190c4e4f9fecd2c5" +checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" dependencies = [ "const-hex", "dunce", "heck", - "indexmap 2.1.0", + "indexmap 2.2.1", "proc-macro-error", "proc-macro2", "quote", @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783eb720b73d38f9d4c1fb9890e4db6bc8c708f7aa77d3071a19e06091ecd1c9" +checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -418,14 +418,13 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -473,6 +472,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.66.1" @@ -583,9 +591,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" dependencies = [ "bytemuck_derive", ] @@ -657,9 +665,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", @@ -777,9 +785,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "da01daa5f6d41c91358398e8db4dde38e292378da1f28300b59ef4732b879454" dependencies = [ "darling_core", "darling_macro", @@ -787,9 +795,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "f44f6238b948a3c6c3073cdf53bb0c2d5e024ee27e0f35bfe9d556a12395808a" dependencies = [ "fnv", "ident_case", @@ -801,9 +809,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "0d2d88bd93979b1feb760a6b5c531ac5ba06bd63e74894c377af02faee07b9cd" dependencies = [ "darling_core", "quote", @@ -1358,7 +1366,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.1", "slab", "tokio", "tokio-util", @@ -1607,9 +1615,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -2098,18 +2106,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", @@ -2338,9 +2346,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -2888,18 +2896,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", @@ -2908,11 +2916,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "itoa", "ryu", "serde", @@ -2932,15 +2940,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58c3a1b3e418f61c25b2aeb43fc6c95eaa252b8cecdda67f401943e9e08d33f" +checksum = "f5c9fdb6b00a489875b22efd4b78fe2b363b72265cc5f6eb2e2b9ee270e6140c" dependencies = [ "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.1.0", + "indexmap 2.2.1", "serde", "serde_json", "serde_with_macros", @@ -2949,9 +2957,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2068b437a31fc68f25dd7edc296b078f04b45145c199d8eed9866e45f1ff274" +checksum = "dbff351eb4b33600a2e138dfa0b10b65a238ea8ff8fb2387c422c5022a3e8298" dependencies = [ "darling", "proc-macro2", @@ -3161,9 +3169,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cfbd642e1748fd9e47951973abfa78f825b11fbf68af9e6b9db4c983a770166" +checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" dependencies = [ "paste", "proc-macro2", @@ -3374,7 +3382,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3385,7 +3393,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3396,7 +3404,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3866,9 +3874,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.34" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] @@ -3955,8 +3963,12 @@ dependencies = [ name = "zeth-lib" version = "0.1.0" dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-rlp-derive", "alloy-sol-types", "anyhow", + "bincode", "bytes", "chrono", "ethers-core", @@ -3988,6 +4000,7 @@ dependencies = [ "bytes", "ethers-core", "k256", + "log", "revm-primitives", "rlp", "serde", diff --git a/guests/op-block/src/main.rs b/guests/op-block/src/main.rs index 623bd611..1e2c2a3e 100644 --- a/guests/op-block/src/main.rs +++ b/guests/op-block/src/main.rs @@ -26,10 +26,15 @@ pub fn main() { // Read the input previous block and transaction data let input = env::read(); // Build the resulting block - let (header, state) = OptimismStrategy::build_from(&OP_MAINNET_CHAIN_SPEC, input) + let mut output = OptimismStrategy::build_from(&OP_MAINNET_CHAIN_SPEC, input) .expect("Failed to build the resulting block"); - // Output the resulting block's hash to the journal - env::commit(&header.hash()); + // Abridge successful construction results + if let Some(replaced_state) = output.replace_state_with_hash() { + // Leak memory, save cycles + core::mem::forget(replaced_state); + } + // Output the construction result + env::commit(&output); // Leak memory, save cycles - core::mem::forget((header, state)); + core::mem::forget(output); } diff --git a/guests/op-compose/Cargo.lock b/guests/op-compose/Cargo.lock index b836ca1d..248e5763 100644 --- a/guests/op-compose/Cargo.lock +++ b/guests/op-compose/Cargo.lock @@ -52,9 +52,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "alloy-primitives" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3729132072f369bc4e8e6e070f9cf4deb3490fc9b9eea6f71f75ec19406df811" +checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" dependencies = [ "alloy-rlp", "bytes", @@ -74,49 +74,48 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc0fac0fc16baf1f63f78b47c3d24718f3619b0714076f6a02957d808d52cbef" +checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" dependencies = [ "arrayvec", "bytes", - "smol_str", ] [[package]] name = "alloy-rlp-derive" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0391754c09fab4eae3404d19d0d297aa1c670c1775ab51d8a5312afeca23157" +checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "alloy-sol-macro" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5531f0a16e36c547e68c73a1638bea1f26237ee8ae785527190c4e4f9fecd2c5" +checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" dependencies = [ "const-hex", "dunce", "heck", - "indexmap 2.1.0", + "indexmap 2.2.1", "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-types" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783eb720b73d38f9d4c1fb9890e4db6bc8c708f7aa77d3071a19e06091ecd1c9" +checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -141,9 +140,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" [[package]] name = "ark-bn254" @@ -387,13 +386,13 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-trait" -version = "0.1.74" +version = "0.1.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" +checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -419,14 +418,13 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -464,9 +462,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -474,6 +472,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.66.1" @@ -493,7 +500,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.39", + "syn 2.0.48", "which", ] @@ -584,9 +591,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" dependencies = [ "bytemuck_derive", ] @@ -599,7 +606,7 @@ checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -658,22 +665,22 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", "num-traits", "serde", - "windows-targets", + "windows-targets 0.52.0", ] [[package]] name = "clang-sys" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", @@ -695,9 +702,9 @@ dependencies = [ [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "convert_case" @@ -707,9 +714,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -717,9 +724,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core2" @@ -732,9 +739,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -778,9 +785,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "da01daa5f6d41c91358398e8db4dde38e292378da1f28300b59ef4732b879454" dependencies = [ "darling_core", "darling_macro", @@ -788,27 +795,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "f44f6238b948a3c6c3073cdf53bb0c2d5e024ee27e0f35bfe9d556a12395808a" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "0d2d88bd93979b1feb760a6b5c531ac5ba06bd63e74894c377af02faee07b9cd" dependencies = [ "darling_core", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -819,9 +826,9 @@ checksum = "7762d17f1241643615821a8455a0b2c3e803784b058693d990b11f2dce25a0ca" [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "der" @@ -835,9 +842,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", "serde", @@ -922,9 +929,9 @@ checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "elf" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6e7d85896690fe195447717af8eceae0593ac2196fd42fe88c184e904406ce" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" [[package]] name = "elliptic-curve" @@ -960,7 +967,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe81b5c06ecfdbc71dd845216f225f53b62a10cb8a16c946836a3467f701d05b" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "hex", "k256", @@ -974,13 +981,13 @@ dependencies = [ [[package]] name = "enumn" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" +checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -991,12 +998,12 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1049,9 +1056,9 @@ dependencies = [ [[package]] name = "ethers-core" -version = "2.0.11" +version = "2.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f03e0bdc216eeb9e355b90cf610ef6c5bb8aca631f97b5ae9980ce34ea7878d" +checksum = "918b1a9ba585ea61022647def2f27c29ba19f6d2a4a4c8f68a9ae97fd5769737" dependencies = [ "arrayvec", "bytes", @@ -1082,7 +1089,7 @@ checksum = "25d6c0c9455d93d4990c06e049abf9b30daf148cf461ee939c11d88907c60816" dependencies = [ "async-trait", "auto_impl", - "base64 0.21.5", + "base64 0.21.7", "bytes", "const-hex", "enr", @@ -1169,9 +1176,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -1184,9 +1191,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1199,9 +1206,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1209,15 +1216,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1226,32 +1233,32 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" @@ -1265,9 +1272,9 @@ dependencies = [ [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1303,9 +1310,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -1314,9 +1321,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "glob" @@ -1349,9 +1356,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -1359,7 +1366,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.1", "slab", "tokio", "tokio-util", @@ -1409,9 +1416,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f" [[package]] name = "hex" @@ -1439,11 +1446,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -1459,9 +1466,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -1482,9 +1489,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -1497,7 +1504,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.10", + "socket2", "tokio", "tower-service", "tracing", @@ -1520,9 +1527,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1549,9 +1556,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1608,9 +1615,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1643,15 +1650,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.65" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1" dependencies = [ "wasm-bindgen", ] @@ -1662,7 +1669,7 @@ version = "8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "pem", "ring 0.16.20", "serde", @@ -1673,8 +1680,7 @@ dependencies = [ [[package]] name = "k256" version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +source = "git+https://github.com/risc0/RustCrypto-elliptic-curves?tag=k256/v0.13.3-risczero.0#d4f457a04410397cbb652a67c168b6cd6e9757c4" dependencies = [ "cfg-if", "ecdsa", @@ -1686,9 +1692,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -1720,9 +1726,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.150" +version = "0.2.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" [[package]] name = "libflate" @@ -1750,12 +1756,12 @@ dependencies = [ [[package]] name = "libloading" -version = "0.7.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" dependencies = [ "cfg-if", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1766,9 +1772,9 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "linux-raw-sys" -version = "0.4.11" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -1788,9 +1794,9 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "mime" @@ -1815,13 +1821,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" +checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -1876,7 +1882,7 @@ checksum = "cfb77679af88f8b125209d354a202862602672222e7f2313fdd6dc349bad4712" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -1934,30 +1940,30 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -2004,9 +2010,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.5" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" +checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" dependencies = [ "arrayvec", "bitvec", @@ -2018,11 +2024,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.5" +version = "3.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" +checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate 2.0.0", "proc-macro2", "quote", "syn 1.0.109", @@ -2048,7 +2054,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-targets", + "windows-targets 0.48.5", ] [[package]] @@ -2074,15 +2080,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" dependencies = [ "memchr", "thiserror", @@ -2101,22 +2107,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2155,12 +2161,12 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "prettyplease" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" +checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5" dependencies = [ "proc-macro2", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2196,6 +2202,15 @@ dependencies = [ "toml_edit 0.20.7", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.0", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -2222,9 +2237,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.69" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] @@ -2257,17 +2272,18 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] [[package]] name = "radium" -version = "0.7.1" -source = "git+https://github.com/ferrilab/radium.git?rev=723bed5#723bed5abd75994ee4b7221b8b12c9f4e77ce408" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "rand" @@ -2319,9 +2335,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.2" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", @@ -2331,9 +2347,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -2348,11 +2364,11 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -2466,16 +2482,16 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.5" +version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb0205304757e5d899b9c2e448b867ffd03ae7f988002e47cd24954391394d0b" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" dependencies = [ "cc", "getrandom", "libc", "spin 0.9.8", "untrusted 0.9.0", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -2582,7 +2598,7 @@ dependencies = [ "risc0-zkp", "risc0-zkvm-platform", "rrs-lib", - "semver 1.0.20", + "semver 1.0.21", "serde", "sha2", "tracing", @@ -2700,30 +2716,30 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.20", + "semver 1.0.21", ] [[package]] name = "rustix" -version = "0.38.25" +version = "0.38.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca" dependencies = [ "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "rustls" -version = "0.21.9" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.5", + "ring 0.17.7", "rustls-webpki", "sct", ] @@ -2734,7 +2750,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", ] [[package]] @@ -2743,7 +2759,7 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.5", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -2767,9 +2783,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "scale-info" @@ -2807,7 +2823,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.5", + "ring 0.17.7", "untrusted 0.9.0", ] @@ -2854,9 +2870,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" [[package]] name = "semver-parser" @@ -2881,31 +2897,31 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.192" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bca2a08484b285dcb282d0f67b26cadc0df8b19f8c12502c13d966bf9482f001" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.192" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c7207fbec9faa48073f3e3074cbe553af6ea512d7c21ba46e434e70ea9fbc1" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "itoa", "ryu", "serde", @@ -2925,15 +2941,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.4.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +checksum = "f5c9fdb6b00a489875b22efd4b78fe2b363b72265cc5f6eb2e2b9ee270e6140c" dependencies = [ - "base64 0.21.5", + "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.1.0", + "indexmap 2.2.1", "serde", "serde_json", "serde_with_macros", @@ -2942,14 +2958,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.4.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +checksum = "dbff351eb4b33600a2e138dfa0b10b65a238ea8ff8fb2387c422c5022a3e8298" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -2995,9 +3011,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" @@ -3041,28 +3057,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] -name = "smol_str" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" -dependencies = [ - "serde", -] - -[[package]] -name = "socket2" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" -dependencies = [ - "libc", - "winapi", -] +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "socket2" @@ -3071,7 +3068,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -3088,9 +3085,9 @@ checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", @@ -3127,7 +3124,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3162,9 +3159,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" dependencies = [ "proc-macro2", "quote", @@ -3173,14 +3170,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cfbd642e1748fd9e47951973abfa78f825b11fbf68af9e6b9db4c983a770166" +checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3212,35 +3209,35 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa" dependencies = [ "cfg-if", "fastrand", "redox_syscall", "rustix", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.50" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3254,9 +3251,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" dependencies = [ "deranged", "itoa", @@ -3274,9 +3271,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" dependencies = [ "time-core", ] @@ -3307,9 +3304,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.35.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" dependencies = [ "backtrace", "bytes", @@ -3319,9 +3316,9 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2 0.5.5", + "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -3332,7 +3329,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3386,7 +3383,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3397,7 +3394,18 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +dependencies = [ + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3428,7 +3436,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3462,9 +3470,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" @@ -3518,9 +3526,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -3557,9 +3565,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -3610,9 +3618,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -3620,24 +3628,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.38" +version = "0.4.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" +checksum = "bde2032aeb86bdfaecc8b261eef3cba735cc426c1f3a3416d1e0791be95fc461" dependencies = [ "cfg-if", "js-sys", @@ -3647,9 +3655,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3657,28 +3665,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.88" +version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" +checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "58cd2333b6e0be7a39605f0e255892fd7418a682d8da8fe042fe25128794d2ed" dependencies = [ "js-sys", "wasm-bindgen", @@ -3686,9 +3694,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.2" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14247bb57be4f377dfb94c72830b8ce8fc6beac03cf4bf7b9732eadd414123fc" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "which" @@ -3726,11 +3734,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets", + "windows-targets 0.52.0", ] [[package]] @@ -3739,7 +3747,16 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.0", ] [[package]] @@ -3748,13 +3765,28 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +dependencies = [ + "windows_aarch64_gnullvm 0.52.0", + "windows_aarch64_msvc 0.52.0", + "windows_i686_gnu 0.52.0", + "windows_i686_msvc 0.52.0", + "windows_x86_64_gnu 0.52.0", + "windows_x86_64_gnullvm 0.52.0", + "windows_x86_64_msvc 0.52.0", ] [[package]] @@ -3763,47 +3795,89 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" + [[package]] name = "windows_aarch64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" + [[package]] name = "windows_i686_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" + [[package]] name = "windows_i686_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" + [[package]] name = "windows_x86_64_gnu" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" + [[package]] name = "windows_x86_64_gnullvm" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" + [[package]] name = "windows_x86_64_msvc" version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" + [[package]] name = "winnow" -version = "0.5.19" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] @@ -3815,7 +3889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ "cfg-if", - "windows-sys", + "windows-sys 0.48.0", ] [[package]] @@ -3848,22 +3922,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.26" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.26" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] @@ -3883,15 +3957,19 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.48", ] [[package]] name = "zeth-lib" version = "0.1.0" dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-rlp-derive", "alloy-sol-types", "anyhow", + "bincode", "bytes", "chrono", "ethers-core", @@ -3923,6 +4001,7 @@ dependencies = [ "bytes", "ethers-core", "k256", + "log", "revm-primitives", "rlp", "serde", @@ -3930,8 +4009,3 @@ dependencies = [ "sha3", "thiserror", ] - -[[patch.unused]] -name = "k256" -version = "0.13.1" -source = "git+https://github.com/risc0/RustCrypto-elliptic-curves?tag=k256/v0.13.1-risc0#44b1fc2b317e76bb150636cf67d0fbdfcac39601" diff --git a/guests/op-compose/Cargo.toml b/guests/op-compose/Cargo.toml index e255ca0d..6bf3b014 100644 --- a/guests/op-compose/Cargo.toml +++ b/guests/op-compose/Cargo.toml @@ -11,10 +11,9 @@ zeth-lib = { path = "../../lib", default-features = false } zeth-primitives = { path = "../../primitives", default-features = false } [patch.crates-io] -radium = { git = 'https://github.com/ferrilab/radium.git', rev = "723bed5" } # use optimized risc0 circuit crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.2-risc0" } -k256 = { git = "https://github.com/risc0/RustCrypto-elliptic-curves", tag = "k256/v0.13.1-risc0" } +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" } [profile.release] diff --git a/guests/op-derive/Cargo.lock b/guests/op-derive/Cargo.lock index f88ab166..2eebe06c 100644 --- a/guests/op-derive/Cargo.lock +++ b/guests/op-derive/Cargo.lock @@ -52,9 +52,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "alloy-primitives" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3729132072f369bc4e8e6e070f9cf4deb3490fc9b9eea6f71f75ec19406df811" +checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" dependencies = [ "alloy-rlp", "bytes", @@ -95,14 +95,14 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5531f0a16e36c547e68c73a1638bea1f26237ee8ae785527190c4e4f9fecd2c5" +checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" dependencies = [ "const-hex", "dunce", "heck", - "indexmap 2.1.0", + "indexmap 2.2.1", "proc-macro-error", "proc-macro2", "quote", @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783eb720b73d38f9d4c1fb9890e4db6bc8c708f7aa77d3071a19e06091ecd1c9" +checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -418,14 +418,13 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -473,6 +472,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.66.1" @@ -583,9 +591,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" dependencies = [ "bytemuck_derive", ] @@ -657,9 +665,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", @@ -777,9 +785,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "da01daa5f6d41c91358398e8db4dde38e292378da1f28300b59ef4732b879454" dependencies = [ "darling_core", "darling_macro", @@ -787,9 +795,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "f44f6238b948a3c6c3073cdf53bb0c2d5e024ee27e0f35bfe9d556a12395808a" dependencies = [ "fnv", "ident_case", @@ -801,9 +809,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "0d2d88bd93979b1feb760a6b5c531ac5ba06bd63e74894c377af02faee07b9cd" dependencies = [ "darling_core", "quote", @@ -1358,7 +1366,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.1", "slab", "tokio", "tokio-util", @@ -1607,9 +1615,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -2099,18 +2107,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", @@ -2339,9 +2347,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -2889,18 +2897,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", @@ -2909,11 +2917,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "itoa", "ryu", "serde", @@ -2933,15 +2941,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58c3a1b3e418f61c25b2aeb43fc6c95eaa252b8cecdda67f401943e9e08d33f" +checksum = "f5c9fdb6b00a489875b22efd4b78fe2b363b72265cc5f6eb2e2b9ee270e6140c" dependencies = [ "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.1.0", + "indexmap 2.2.1", "serde", "serde_json", "serde_with_macros", @@ -2950,9 +2958,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2068b437a31fc68f25dd7edc296b078f04b45145c199d8eed9866e45f1ff274" +checksum = "dbff351eb4b33600a2e138dfa0b10b65a238ea8ff8fb2387c422c5022a3e8298" dependencies = [ "darling", "proc-macro2", @@ -3162,9 +3170,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cfbd642e1748fd9e47951973abfa78f825b11fbf68af9e6b9db4c983a770166" +checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" dependencies = [ "paste", "proc-macro2", @@ -3375,7 +3383,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3386,7 +3394,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3397,7 +3405,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3867,9 +3875,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.34" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] @@ -3956,8 +3964,12 @@ dependencies = [ name = "zeth-lib" version = "0.1.0" dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-rlp-derive", "alloy-sol-types", "anyhow", + "bincode", "bytes", "chrono", "ethers-core", @@ -3989,6 +4001,7 @@ dependencies = [ "bytes", "ethers-core", "k256", + "log", "revm-primitives", "rlp", "serde", diff --git a/guests/op-derive/src/main.rs b/guests/op-derive/src/main.rs index 4f7c34db..123dac7e 100644 --- a/guests/op-derive/src/main.rs +++ b/guests/op-derive/src/main.rs @@ -23,10 +23,10 @@ risc0_zkvm::guest::entry!(main); pub fn main() { let derive_input: DeriveInput = env::read(); - let mut derive_machine = DeriveMachine::new(&OPTIMISM_CHAIN_SPEC, derive_input) + let mut derive_machine = DeriveMachine::new(&OPTIMISM_CHAIN_SPEC, derive_input, None) .expect("Could not create derive machine"); let output = derive_machine - .derive() + .derive(None) .expect("Failed to process derivation input"); env::commit(&output); } diff --git a/host/Cargo.toml b/host/Cargo.toml index 7c9d2f4f..cb83167a 100644 --- a/host/Cargo.toml +++ b/host/Cargo.toml @@ -21,6 +21,7 @@ ruint = { version = "1.10", default-features = false } serde = "1.0" tempfile = "3.6" tokio = { version = "1.23", features = ["full"] } +tracing = { version = "0.1", features = ["log"] } zeth-guests = { path = "../guests" } zeth-lib = { path = "../lib" } zeth-primitives = { path = "../primitives" } @@ -32,4 +33,10 @@ rstest = "0.18" [features] metal = [ "risc0-zkvm/metal" -] \ No newline at end of file +] +cuda = [ + "risc0-zkvm/cuda" +] +disable-dev-mode = [ + "risc0-zkvm/disable-dev-mode" +] diff --git a/host/src/cli.rs b/host/src/cli.rs index fa320978..3b2669e7 100644 --- a/host/src/cli.rs +++ b/host/src/cli.rs @@ -51,6 +51,13 @@ impl Cli { _ => None, } } + + pub fn execution_label(&self) -> String { + let sys_time = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap(); + format!("{}_{}", sys_time.as_secs(), self.to_string()) + } } impl ToString for Cli { @@ -119,9 +126,9 @@ pub struct CoreArgs { /// URL of the Optimism RPC node. pub op_rpc_url: Option, - #[clap(short, long, require_equals = true, num_args = 0..=1, default_missing_value = "rpc_cache")] + #[clap(short, long, require_equals = true, num_args = 0..=1, default_missing_value = "cache_rpc")] /// Use a local directory as a cache for RPC calls. Accepts a custom directory. - /// [default: host/testdata] + /// [default: cache_rpc] pub cache: Option, #[clap(short, long, require_equals = true)] @@ -135,9 +142,9 @@ pub struct CoreArgs { #[derive(clap::Args, Debug, Clone)] pub struct ExecutorArgs { - #[clap(short, long, require_equals = true, default_value_t = 20)] + #[clap(short = 'x', long, require_equals = true, default_value_t = 20)] /// The maximum segment cycle count as a power of 2. - pub local_exec: u32, + pub execution_po2: u32, #[clap(short, long, default_value_t = false)] /// Whether to profile the zkVM execution @@ -188,5 +195,5 @@ pub struct VerifyArgs { pub core_args: CoreArgs, #[clap(short, long, require_equals = true)] /// Verify the receipt from the provided Bonsai Session UUID. - pub receipt_bonsai_uuid: Option, + pub bonsai_receipt_uuid: String, } diff --git a/host/src/lib.rs b/host/src/lib.rs index 572239b2..327d03f1 100644 --- a/host/src/lib.rs +++ b/host/src/lib.rs @@ -12,30 +12,46 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{ - fs, - path::{Path, PathBuf}, -}; +use std::{fs, path::Path}; -use risc0_zkvm::Receipt; +use risc0_zkvm::{is_dev_mode, Receipt}; +use tracing::debug; pub mod cli; pub mod operations; -pub fn cache_file_path(cache_path: &Path, network: &str, block_no: u64, ext: &str) -> PathBuf { - cache_path - .join(network) - .join(block_no.to_string()) - .with_extension(ext) -} +pub fn load_receipt(file_name: &String) -> anyhow::Result> { + if is_dev_mode() { + // Nothing to load + return Ok(None); + } -pub fn save_receipt(file_reference: &String, receipt: &Receipt, index: Option<&mut usize>) { - let receipt_serialized = bincode::serialize(receipt).expect("Failed to serialize receipt!"); - let path = if let Some(number) = index { - *number += 1; - format!("receipt_{}-{}.zkp", file_reference, *number - 1) - } else { - format!("receipt_{}.zkp", file_reference) + let receipt_serialized = match fs::read(zkp_cache_path(file_name)) { + Ok(receipt_serialized) => receipt_serialized, + Err(err) => { + debug!("Could not load cached receipt with label: {}", &file_name); + debug!("{:?}", err); + return Ok(None); + } }; - fs::write(path, receipt_serialized).expect("Failed to save receipt output file."); + + Ok(Some(bincode::deserialize(&receipt_serialized)?)) +} + +pub fn save_receipt(receipt_label: &String, receipt_data: &(String, Receipt)) { + if !is_dev_mode() { + fs::write( + zkp_cache_path(receipt_label), + bincode::serialize(receipt_data).expect("Failed to serialize receipt!"), + ) + .expect("Failed to save receipt output file."); + } +} + +fn zkp_cache_path(receipt_label: &String) -> String { + Path::new("cache_zkp") + .join(format!("{}.zkp", receipt_label)) + .to_str() + .unwrap() + .to_string() } diff --git a/host/src/main.rs b/host/src/main.rs index e8a1a2ed..319f0499 100644 --- a/host/src/main.rs +++ b/host/src/main.rs @@ -16,9 +16,10 @@ extern crate core; use anyhow::Result; use clap::Parser; +use log::info; use zeth::{ cli::Cli, - operations::{chains, info, rollups}, + operations::{chains, info::op_info, rollups}, }; use zeth_guests::*; use zeth_lib::{ @@ -29,27 +30,39 @@ use zeth_lib::{ #[tokio::main] async fn main() -> Result<()> { env_logger::init(); + info!("Using the following image ids:"); + info!( + "eth-block: {}", + hex::encode(bytemuck::cast_slice(Ð_BLOCK_ID)) + ); + info!( + "op-block: {}", + hex::encode(bytemuck::cast_slice(&OP_BLOCK_ID)) + ); + info!( + "op-derive: {}", + hex::encode(bytemuck::cast_slice(&OP_DERIVE_ID)) + ); + info!( + "op-compose: {}", + hex::encode(bytemuck::cast_slice(&OP_COMPOSE_ID)) + ); let cli = Cli::parse(); // Run simple debug info command if let Cli::OpInfo(..) = &cli { - return info::op_info(cli).await; + return op_info(cli).await; } // Execute other commands let core_args = cli.core_args(); - let sys_time = std::time::SystemTime::now() - .duration_since(std::time::UNIX_EPOCH) - .unwrap(); - let file_reference = format!("{}_{}", sys_time.as_secs(), cli.to_string()); match core_args.network { Network::Ethereum => { let rpc_url = core_args.eth_rpc_url.clone(); chains::build_chain_blocks::( cli, - &file_reference, rpc_url, ETH_MAINNET_CHAIN_SPEC.clone(), ETH_BLOCK_ELF, @@ -60,7 +73,6 @@ async fn main() -> Result<()> { let rpc_url = core_args.op_rpc_url.clone(); chains::build_chain_blocks::( cli, - &file_reference, rpc_url, OP_MAINNET_CHAIN_SPEC.clone(), OP_BLOCK_ELF, @@ -69,9 +81,9 @@ async fn main() -> Result<()> { } Network::OptimismDerived => { if let Some(composition_size) = cli.composition() { - rollups::compose_derived_rollup_blocks(cli, composition_size, &file_reference).await + rollups::compose_derived_rollup_blocks(cli, composition_size).await } else { - rollups::derive_rollup_blocks(cli, &file_reference).await + rollups::derive_rollup_blocks(cli).await } } } diff --git a/host/src/operations/chains.rs b/host/src/operations/chains.rs index 584971a9..6ce2eade 100644 --- a/host/src/operations/chains.rs +++ b/host/src/operations/chains.rs @@ -16,24 +16,24 @@ use std::fmt::Debug; use anyhow::Context; use ethers_core::types::Transaction as EthersTransaction; -use log::info; +use log::{info, warn}; +use risc0_zkvm::compute_image_id; use serde::{Deserialize, Serialize}; use zeth_lib::{ builder::BlockBuilderStrategy, consts::ChainSpec, - host::{preflight::Preflight, verify::Verifier}, - input::Input, + host::{cache_file_path, preflight::Preflight, verify::Verifier}, + input::BlockBuildInput, + output::BlockBuildOutput, }; use crate::{ - cache_file_path, cli::Cli, - operations::{execute, maybe_prove}, + operations::{execute, maybe_prove, verify_bonsai_receipt}, }; pub async fn build_chain_blocks( cli: Cli, - file_reference: &String, rpc_url: Option, chain_spec: ChainSpec, guest_elf: &[u8], @@ -55,37 +55,49 @@ where let init_spec = chain_spec.clone(); let preflight_result = tokio::task::spawn_blocking(move || { - N::run_preflight(init_spec, rpc_cache, rpc_url, core_args.block_number) + N::preflight_with_external_data(init_spec, rpc_cache, rpc_url, core_args.block_number) }) .await?; let preflight_data = preflight_result.context("preflight failed")?; // Create the guest input from [Init] - let input: Input = preflight_data + let input: BlockBuildInput = preflight_data .clone() .try_into() .context("invalid preflight data")?; // Verify that the transactions run correctly info!("Running from memory ..."); - let (header, state_trie) = - N::build_from(&chain_spec, input.clone()).context("Error while building block")?; + let output = N::build_from(&chain_spec, input.clone()).context("Error while building block")?; - info!("Verifying final state using provider data ..."); - preflight_data.verify_block(&header, &state_trie)?; + match &output { + BlockBuildOutput::SUCCESS { + hash: new_block_hash, + head: new_block_head, + state: new_block_state, + .. + } => { + info!("Verifying final state using provider data ..."); + preflight_data.verify_block(new_block_head, new_block_state)?; - info!("Final block hash derived successfully. {}", header.hash()); + info!("Final block hash derived successfully. {}", new_block_hash); + } + BlockBuildOutput::FAILURE { .. } => { + warn!("Proving bad block construction!") + } + } + let compressed_output = output.with_state_hashed(); match &cli { Cli::Build(..) => {} Cli::Run(run_args) => { execute( &input, - run_args.exec_args.local_exec, + run_args.exec_args.execution_po2, run_args.exec_args.profile, guest_elf, - &preflight_data.header.hash(), - file_reference, + &compressed_output, + &cli.execution_label(), ); } Cli::Prove(..) => { @@ -93,119 +105,24 @@ where &cli, &input, guest_elf, - &preflight_data.header.hash(), - vec![], - file_reference, - None, - ); + &compressed_output, + Default::default(), + ) + .await; } - Cli::Verify(..) => { - unimplemented!() + Cli::Verify(verify_args) => { + verify_bonsai_receipt( + compute_image_id(guest_elf)?, + &compressed_output, + verify_args.bonsai_receipt_uuid.clone(), + 4, + ) + .await?; } Cli::OpInfo(..) => { unreachable!() } } - // let mut bonsai_session_uuid = args.verify_receipt_bonsai_uuid; - - // Run in Bonsai (if requested) - // if bonsai_session_uuid.is_none() && args.submit_to_bonsai { - // info!("Creating Bonsai client"); - // let client = bonsai_sdk::Client::from_env(risc0_zkvm::VERSION) - // .expect("Could not create Bonsai client"); - // - // // create the memoryImg, upload it and return the imageId - // info!("Uploading memory image"); - // let img_id = { - // let program = Program::load_elf(guest_elf, risc0_zkvm::GUEST_MAX_MEM as u32) - // .expect("Could not load ELF"); - // let image = MemoryImage::new(&program, risc0_zkvm::PAGE_SIZE as u32) - // .expect("Could not create memory image"); - // let image_id = hex::encode(image.compute_id()); - // let image = bincode::serialize(&image).expect("Failed to serialize memory - // img"); - // - // client - // .upload_img(&image_id, image) - // .expect("Could not upload ELF"); - // image_id - // }; - // - // // Prepare input data and upload it. - // info!("Uploading inputs"); - // let input_data = to_vec(&input).unwrap(); - // let input_data = bytemuck::cast_slice(&input_data).to_vec(); - // let input_id = client - // .upload_input(input_data) - // .expect("Could not upload inputs"); - // - // // Start a session running the prover - // info!("Starting session"); - // let session = client - // .create_session(img_id, input_id) - // .expect("Could not create Bonsai session"); - // - // println!("Bonsai session UUID: {}", session.uuid); - // bonsai_session_uuid = Some(session.uuid) - // } - - // Verify receipt from Bonsai (if requested) - // if let Some(session_uuid) = bonsai_session_uuid { - // let client = bonsai_sdk::Client::from_env(risc0_zkvm::VERSION) - // .expect("Could not create Bonsai client"); - // let session = bonsai_sdk::SessionId { uuid: session_uuid }; - // - // loop { - // let res = session - // .status(&client) - // .expect("Could not fetch Bonsai status"); - // if res.status == "RUNNING" { - // println!( - // "Current status: {} - state: {} - continue polling...", - // res.status, - // res.state.unwrap_or_default() - // ); - // tokio::time::sleep(std::time::Duration::from_secs(15)).await; - // continue; - // } - // if res.status == "SUCCEEDED" { - // // Download the receipt, containing the output - // let receipt_url = res - // .receipt_url - // .expect("API error, missing receipt on completed session"); - // - // let receipt_buf = client - // .download(&receipt_url) - // .expect("Could not download receipt"); - // let receipt: Receipt = - // bincode::deserialize(&receipt_buf).expect("Could not deserialize - // receipt"); receipt - // .verify(guest_id) - // .expect("Receipt verification failed"); - // - // let expected_hash = preflight_data.header.hash(); - // let found_hash: BlockHash = receipt.journal.decode().unwrap(); - // - // if found_hash == expected_hash { - // info!("Block hash (from Bonsai): {}", found_hash); - // } else { - // error!( - // "Final block hash mismatch (from Bonsai) {} (expected {})", - // found_hash, expected_hash, - // ); - // } - // } else { - // panic!( - // "Workflow exited: {} - | err: {}", - // res.status, - // res.error_msg.unwrap_or_default() - // ); - // } - // - // break; - // } - // } - Ok(()) } diff --git a/host/src/operations/info.rs b/host/src/operations/info.rs index 38b3cb03..e70717dd 100644 --- a/host/src/operations/info.rs +++ b/host/src/operations/info.rs @@ -16,11 +16,14 @@ use alloy_sol_types::SolInterface; use log::warn; use zeth_lib::{ consts::Network, - host::provider::{new_provider, BlockQuery}, + host::{ + cache_file_path, + provider::{new_provider, BlockQuery}, + }, optimism::OpSystemInfo, }; -use crate::{cache_file_path, cli::Cli}; +use crate::cli::Cli; pub async fn op_info(cli: Cli) -> anyhow::Result<()> { let core_args = cli.core_args().clone(); diff --git a/host/src/operations/mod.rs b/host/src/operations/mod.rs index 96804455..9e1a69bd 100644 --- a/host/src/operations/mod.rs +++ b/host/src/operations/mod.rs @@ -18,67 +18,222 @@ pub mod rollups; use std::fmt::Debug; -use log::{error, info}; +use log::{debug, error, info, warn}; use risc0_zkvm::{ - default_prover, serde::to_vec, Assumption, ExecutorEnv, ExecutorImpl, FileSegmentRef, Receipt, - Session, + compute_image_id, default_prover, serde::to_vec, sha::Digest, Assumption, ExecutorEnv, + ExecutorImpl, FileSegmentRef, Receipt, Session, }; use serde::{de::DeserializeOwned, Serialize}; use tempfile::tempdir; +use zeth_primitives::keccak::keccak; -use crate::{cli::Cli, save_receipt}; +use crate::{cli::Cli, load_receipt, save_receipt}; -pub fn maybe_prove( - cli: &Cli, - input: &I, - elf: &[u8], +pub async fn verify_bonsai_receipt( + image_id: Digest, expected_output: &O, - assumptions: Vec, - file_reference: &String, - receipt_index: Option<&mut usize>, -) -> Option { - if let Cli::Prove(prove_args) = cli { - if prove_args.submit_to_bonsai { - unimplemented!() + uuid: String, + max_retries: usize, +) -> anyhow::Result<(String, Receipt)> { + info!("Tracking receipt uuid: {}", uuid); + let session = bonsai_sdk::alpha::SessionId { uuid }; + + loop { + let mut res = None; + for attempt in 1..=max_retries { + let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?; + + match session.status(&client) { + Ok(response) => { + res = Some(response); + break; + } + Err(err) => { + if attempt == max_retries { + anyhow::bail!(err); + } + warn!( + "Attempt {}/{} for session status request: {:?}", + attempt, max_retries, err + ); + std::thread::sleep(std::time::Duration::from_secs(15)); + continue; + } + } } - // run prover - let receipt = prove( - prove_args.exec_args.local_exec, - to_vec(input).expect("Could not serialize composition prep input!"), - elf, - assumptions, - prove_args.exec_args.profile, - file_reference, - ); - // verify output - let output_guest: O = receipt.journal.decode().unwrap(); - if expected_output == &output_guest { - info!("Executor succeeded"); + + let res = res.unwrap(); + + if res.status == "RUNNING" { + info!( + "Current status: {} - state: {} - continue polling...", + res.status, + res.state.unwrap_or_default() + ); + std::thread::sleep(std::time::Duration::from_secs(15)); + } else if res.status == "SUCCEEDED" { + // Download the receipt, containing the output + let receipt_url = res + .receipt_url + .expect("API error, missing receipt on completed session"); + let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?; + let receipt_buf = client.download(&receipt_url)?; + let receipt: Receipt = bincode::deserialize(&receipt_buf)?; + receipt + .verify(image_id) + .expect("Receipt verification failed"); + // verify output + let receipt_output: O = receipt.journal.decode().unwrap(); + if expected_output == &receipt_output { + info!("Receipt validated!"); + } else { + error!( + "Output mismatch! Receipt: {:?}, expected: {:?}", + receipt_output, expected_output, + ); + } + return Ok((session.uuid, receipt)); } else { - error!( - "Output mismatch! Executor: {:?}, expected: {:?}", - output_guest, expected_output, + panic!( + "Workflow exited: {} - | err: {}", + res.status, + res.error_msg.unwrap_or_default() ); } - // save receipt - save_receipt(file_reference, &receipt, receipt_index); - // return result - Some(receipt) + } +} + +pub async fn maybe_prove( + cli: &Cli, + input: &I, + elf: &[u8], + expected_output: &O, + assumptions: (Vec, Vec), +) -> Option<(String, Receipt)> { + let Cli::Prove(prove_args) = cli else { + return None; + }; + + let (assumption_instances, assumption_uuids) = assumptions; + let encoded_input = to_vec(input).expect("Could not serialize proving input!"); + + let encoded_output = + to_vec(expected_output).expect("Could not serialize expected proving output!"); + let computed_image_id = compute_image_id(elf).expect("Failed to compute elf image id!"); + + let receipt_label = format!( + "{}-{}", + hex::encode(computed_image_id), + hex::encode(keccak(bytemuck::cast_slice(&encoded_output))) + ); + + // get receipt + let (mut receipt_uuid, receipt, cached) = + if let Ok(Some(cached_data)) = load_receipt(&receipt_label) { + info!("Loaded locally cached receipt"); + (cached_data.0, cached_data.1, true) + } else if prove_args.submit_to_bonsai { + // query bonsai service until it works + loop { + if let Ok(remote_proof) = prove_bonsai( + encoded_input.clone(), + elf, + expected_output, + assumption_uuids.clone(), + ) + .await + { + break (remote_proof.0, remote_proof.1, false); + } + } + } else { + // run prover + ( + Default::default(), + prove_locally( + prove_args.exec_args.execution_po2, + encoded_input, + elf, + assumption_instances, + prove_args.exec_args.profile, + &cli.execution_label(), + ), + false, + ) + }; + + // verify output + let output_guest: O = receipt.journal.decode().unwrap(); + if expected_output == &output_guest { + info!("Prover succeeded"); } else { - None + error!( + "Output mismatch! Prover: {:?}, expected: {:?}", + output_guest, expected_output, + ); } + + // upload receipt to bonsai + if prove_args.submit_to_bonsai && receipt_uuid.is_empty() { + info!("Uploading cached receipt without UUID to Bonsai."); + receipt_uuid = upload_receipt(&receipt) + .await + .expect("Failed to upload cached receipt to Bonsai"); + } + + let result = (receipt_uuid, receipt); + + // save receipt + if !cached { + save_receipt(&receipt_label, &result); + } + + // return result + Some(result) +} + +pub async fn upload_receipt(receipt: &Receipt) -> anyhow::Result { + let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?; + Ok(client.upload_receipt(bincode::serialize(receipt)?)?) +} + +pub async fn prove_bonsai( + encoded_input: Vec, + elf: &[u8], + expected_output: &O, + assumption_uuids: Vec, +) -> anyhow::Result<(String, Receipt)> { + info!("Proving on Bonsai"); + // Compute the image_id, then upload the ELF with the image_id as its key. + let image_id = risc0_zkvm::compute_image_id(elf)?; + let encoded_image_id = hex::encode(image_id); + // Prepare input data + let input_data = bytemuck::cast_slice(&encoded_input).to_vec(); + + let client = bonsai_sdk::alpha_async::get_client_from_env(risc0_zkvm::VERSION).await?; + client.upload_img(&encoded_image_id, elf.to_vec())?; + // upload input + let input_id = client.upload_input(input_data.clone())?; + + let session = client.create_session( + encoded_image_id.clone(), + input_id.clone(), + assumption_uuids.clone(), + )?; + + verify_bonsai_receipt(image_id, expected_output, session.uuid.clone(), 8).await } -pub fn prove( +pub fn prove_locally( segment_limit_po2: u32, encoded_input: Vec, elf: &[u8], assumptions: Vec, profile: bool, - file_reference: &String, + profile_reference: &String, ) -> Receipt { - info!("Proving with segment_limit_po2 = {:?}", segment_limit_po2); - info!( + debug!("Proving with segment_limit_po2 = {:?}", segment_limit_po2); + debug!( "Input size: {} words ( {} MB )", encoded_input.len(), encoded_input.len() * 4 / 1_000_000 @@ -94,7 +249,7 @@ pub fn prove( if profile { info!("Profiling enabled."); - env_builder.enable_profiler(format!("profile_{}.pb", file_reference)); + env_builder.enable_profiler(format!("profile_{}.pb", profile_reference)); } for assumption in assumptions { @@ -111,15 +266,15 @@ pub fn execute( profile: bool, elf: &[u8], expected_output: &O, - file_reference: &String, + profile_reference: &String, ) -> Session { - info!( + debug!( "Running in executor with segment_limit_po2 = {:?}", segment_limit_po2 ); let input = to_vec(input).expect("Could not serialize input!"); - info!( + debug!( "Input size: {} words ( {} MB )", input.len(), input.len() * 4 / 1_000_000 @@ -136,7 +291,7 @@ pub fn execute( if profile { info!("Profiling enabled."); - builder.enable_profiler(format!("profile_{}.pb", file_reference)); + builder.enable_profiler(format!("profile_{}.pb", profile_reference)); } let env = builder.build().unwrap(); diff --git a/host/src/operations/rollups.rs b/host/src/operations/rollups.rs index 6bc4ec72..95784203 100644 --- a/host/src/operations/rollups.rs +++ b/host/src/operations/rollups.rs @@ -15,302 +15,256 @@ use std::collections::VecDeque; use anyhow::Context; -use log::info; +use log::{info, trace}; +use risc0_zkvm::Assumption; use zeth_guests::*; use zeth_lib::{ - host::rpc_db::RpcDb, + builder::{BlockBuilderStrategy, OptimismStrategy}, + consts::{Network, OP_MAINNET_CHAIN_SPEC}, + host::{rpc_db::RpcDb, ProviderFactory}, + input::BlockBuildInput, optimism::{ batcher_db::BatcherDb, composition::{ComposeInput, ComposeInputOperation, ComposeOutputOperation}, config::OPTIMISM_CHAIN_SPEC, DeriveInput, DeriveMachine, }, + output::BlockBuildOutput, }; use zeth_primitives::{ block::Header, mmr::{MerkleMountainRange, MerkleProof}, + transactions::optimism::OptimismTxEssence, }; use crate::{ cli::Cli, - operations::{execute, maybe_prove}, + operations::{maybe_prove, verify_bonsai_receipt}, }; -pub async fn derive_rollup_blocks(cli: Cli, file_reference: &String) -> anyhow::Result<()> { +pub async fn derive_rollup_blocks(cli: Cli) -> anyhow::Result<()> { info!("Fetching data ..."); let core_args = cli.core_args().clone(); - let (derive_input, output) = tokio::task::spawn_blocking(move || { - let derive_input = DeriveInput { - db: RpcDb::new( - core_args.eth_rpc_url.clone(), - core_args.op_rpc_url.clone(), - core_args.cache.clone(), - ), - op_head_block_no: core_args.block_number, - op_derive_block_count: core_args.block_count, - }; - let mut derive_machine = DeriveMachine::new(&OPTIMISM_CHAIN_SPEC, derive_input) - .context("Could not create derive machine")?; - let derive_output = derive_machine.derive().context("could not derive")?; - let derive_input_mem = DeriveInput { - db: derive_machine.derive_input.db.get_mem_db(), - op_head_block_no: core_args.block_number, - op_derive_block_count: core_args.block_count, - }; - let out: anyhow::Result<_> = Ok((derive_input_mem, derive_output)); - out + let op_builder_provider_factory = ProviderFactory::new( + core_args.cache.clone(), + Network::Optimism, + core_args.op_rpc_url.clone(), + ); + + info!("Running preflight"); + let derive_input = DeriveInput { + db: RpcDb::new( + core_args.eth_rpc_url.clone(), + core_args.op_rpc_url.clone(), + core_args.cache.clone(), + ), + op_head_block_no: core_args.block_number, + op_derive_block_count: core_args.block_count, + op_block_outputs: vec![], + block_image_id: OP_BLOCK_ID, + }; + let factory_clone = op_builder_provider_factory.clone(); + let (op_block_inputs, derive_machine, derive_output) = tokio::task::spawn_blocking(move || { + let mut derive_machine = + DeriveMachine::new(&OPTIMISM_CHAIN_SPEC, derive_input, Some(factory_clone)) + .expect("Could not create derive machine"); + let mut op_block_inputs = vec![]; + let derive_output = derive_machine + .derive(Some(&mut op_block_inputs)) + .expect("could not derive"); + (op_block_inputs, derive_machine, derive_output) }) - .await? - .context("preflight failed")?; + .await?; + + let (assumptions, bonsai_receipt_uuids, op_block_outputs) = + build_op_blocks(&cli, op_block_inputs).await; + + let derive_input_mem = DeriveInput { + db: derive_machine.derive_input.db.get_mem_db(), + op_head_block_no: core_args.block_number, + op_derive_block_count: core_args.block_count, + op_block_outputs, + block_image_id: OP_BLOCK_ID, + }; info!("Running from memory ..."); { - let output_mem = DeriveMachine::new(&OPTIMISM_CHAIN_SPEC, derive_input.clone()) - .context("Could not create derive machine")? - .derive() - .unwrap(); - assert_eq!(output, output_mem); + let input_clone = derive_input_mem.clone(); + let output_mem = tokio::task::spawn_blocking(move || { + DeriveMachine::new( + &OPTIMISM_CHAIN_SPEC, + input_clone, + Some(op_builder_provider_factory), + ) + .expect("Could not create derive machine") + .derive(None) + .unwrap() + }) + .await?; + assert_eq!(derive_output, output_mem); } info!("In-memory test complete"); println!( "Eth tail: {} {}", - output.eth_tail.number, output.eth_tail.hash + derive_output.eth_tail.number, derive_output.eth_tail.hash ); - println!("Op Head: {} {}", output.op_head.number, output.op_head.hash); - for derived_block in &output.derived_op_blocks { + println!( + "Op Head: {} {}", + derive_output.op_head.number, derive_output.op_head.hash + ); + for derived_block in &derive_output.derived_op_blocks { println!("Derived: {} {}", derived_block.number, derived_block.hash); } match &cli { Cli::Build(..) => {} - Cli::Run(run_args) => { - execute( - &derive_input, - run_args.exec_args.local_exec, - run_args.exec_args.profile, - OP_DERIVE_ELF, - &output, - file_reference, - ); - } + Cli::Run(..) => {} Cli::Prove(..) => { maybe_prove( &cli, - &derive_input, + &derive_input_mem, OP_DERIVE_ELF, - &output, - vec![], - file_reference, - None, - ); + &derive_output, + (assumptions, bonsai_receipt_uuids), + ) + .await; } - Cli::Verify(..) => { - unimplemented!() + Cli::Verify(verify_args) => { + verify_bonsai_receipt( + OP_DERIVE_ID.into(), + &derive_output, + verify_args.bonsai_receipt_uuid.clone(), + 4, + ) + .await?; } Cli::OpInfo(..) => { unreachable!() } } - // let mut bonsai_session_uuid = args.verify_receipt_bonsai_uuid; - - // Run in Bonsai (if requested) - // if bonsai_session_uuid.is_none() && args.submit_to_bonsai { - // info!("Creating Bonsai client"); - // let client = bonsai_sdk::Client::from_env(risc0_zkvm::VERSION) - // .expect("Could not create Bonsai client"); - // - // // create the memoryImg, upload it and return the imageId - // info!("Uploading memory image"); - // let img_id = { - // let program = Program::load_elf(OP_DERIVE_ELF, risc0_zkvm::GUEST_MAX_MEM as - // u32) .expect("Could not load ELF"); - // let image = MemoryImage::new(&program, risc0_zkvm::PAGE_SIZE as u32) - // .expect("Could not create memory image"); - // let image_id = hex::encode(image.compute_id()); - // let image = bincode::serialize(&image).expect("Failed to serialize memory - // img"); - // - // client - // .upload_img(&image_id, image) - // .expect("Could not upload ELF"); - // image_id - // }; - // - // // Prepare input data and upload it. - // info!("Uploading inputs"); - // let input_data = to_vec(&derive_input).unwrap(); - // let input_data = bytemuck::cast_slice(&input_data).to_vec(); - // let input_id = client - // .upload_input(input_data) - // .expect("Could not upload inputs"); - // - // // Start a session running the prover - // info!("Starting session"); - // let session = client - // .create_session(img_id, input_id) - // .expect("Could not create Bonsai session"); - // - // println!("Bonsai session UUID: {}", session.uuid); - // bonsai_session_uuid = Some(session.uuid) - // } - - // Verify receipt from Bonsai (if requested) - // if let Some(session_uuid) = bonsai_session_uuid { - // let client = bonsai_sdk::Client::from_env(risc0_zkvm::VERSION) - // .expect("Could not create Bonsai client"); - // let session = bonsai_sdk::SessionId { uuid: session_uuid }; - // - // loop { - // let res = session - // .status(&client) - // .expect("Could not fetch Bonsai status"); - // if res.status == "RUNNING" { - // println!( - // "Current status: {} - state: {} - continue polling...", - // res.status, - // res.state.unwrap_or_default() - // ); - // tokio::time::sleep(std::time::Duration::from_secs(15)).await; - // continue; - // } - // if res.status == "SUCCEEDED" { - // // Download the receipt, containing the output - // let receipt_url = res - // .receipt_url - // .expect("API error, missing receipt on completed session"); - // - // let receipt_buf = client - // .download(&receipt_url) - // .expect("Could not download receipt"); - // let receipt: Receipt = - // bincode::deserialize(&receipt_buf).expect("Could not deserialize - // receipt"); receipt - // .verify(OP_DERIVE_ID) - // .expect("Receipt verification failed"); - // - // let bonsai_output: DeriveOutput = receipt.journal.decode().unwrap(); - // - // if output == bonsai_output { - // println!("Bonsai succeeded"); - // } else { - // error!( - // "Output mismatch! Bonsai: {:?}, expected: {:?}", - // bonsai_output, output, - // ); - // } - // } else { - // panic!( - // "Workflow exited: {} - | err: {}", - // res.status, - // res.error_msg.unwrap_or_default() - // ); - // } - // - // break; - // } - // - // info!("Bonsai request completed"); - // } Ok(()) } -pub async fn compose_derived_rollup_blocks( - cli: Cli, - composition_size: u64, - file_reference: &String, -) -> anyhow::Result<()> { +pub async fn compose_derived_rollup_blocks(cli: Cli, composition_size: u64) -> anyhow::Result<()> { let core_args = cli.core_args().clone(); // OP Composition info!("Fetching data ..."); let mut lift_queue = Vec::new(); - let mut receipt_index = 0; - let mut eth_chain: Vec
= Vec::new(); + let mut complete_eth_chain: Vec
= Vec::new(); for op_block_index in (0..core_args.block_count).step_by(composition_size as usize) { let db = RpcDb::new( core_args.eth_rpc_url.clone(), core_args.op_rpc_url.clone(), core_args.cache.clone(), ); - let (input, output, chain) = tokio::task::spawn_blocking(move || { - let derive_input = DeriveInput { - db, - op_head_block_no: core_args.block_number + op_block_index, - op_derive_block_count: composition_size, - }; - let mut derive_machine = DeriveMachine::new(&OPTIMISM_CHAIN_SPEC, derive_input) - .expect("Could not create derive machine"); - let eth_head_no = derive_machine.op_batcher.state.epoch.number; - let eth_head = derive_machine - .derive_input - .db - .get_full_eth_block(eth_head_no) - .context("could not fetch eth head")? - .block_header - .clone(); - let derive_output = derive_machine.derive().context("could not derive")?; - let eth_tail = derive_machine - .derive_input - .db - .get_full_eth_block(derive_output.eth_tail.number) - .context("could not fetch eth tail")? - .block_header - .clone(); - let mut eth_chain = vec![eth_head]; - for block_no in (eth_head_no + 1)..eth_tail.number { - eth_chain.push( - derive_machine - .derive_input - .db - .get_full_eth_block(block_no) - .context("could not fetch eth block")? - .block_header - .clone(), - ); - } - eth_chain.push(eth_tail); + let op_builder_provider_factory = ProviderFactory::new( + core_args.cache.clone(), + Network::Optimism, + core_args.op_rpc_url.clone(), + ); - let derive_input_mem = DeriveInput { - db: derive_machine.derive_input.db.get_mem_db(), - op_head_block_no: core_args.block_number + op_block_index, - op_derive_block_count: composition_size, - }; - let out: anyhow::Result<_> = Ok((derive_input_mem, derive_output, eth_chain)); - out + let derive_input = DeriveInput { + db, + op_head_block_no: core_args.block_number + op_block_index, + op_derive_block_count: composition_size, + op_block_outputs: vec![], + block_image_id: OP_BLOCK_ID, + }; + let factory_clone = op_builder_provider_factory.clone(); + let mut derive_machine = tokio::task::spawn_blocking(move || { + DeriveMachine::new(&OPTIMISM_CHAIN_SPEC, derive_input, Some(factory_clone)) + .expect("Could not create derive machine") }) - .await??; + .await?; + let eth_head_no = derive_machine.op_batcher.state.epoch.number; + let eth_head = derive_machine + .derive_input + .db + .get_full_eth_block(eth_head_no) + .context("could not fetch eth head")? + .block_header + .clone(); + let (op_block_inputs, mut derive_machine, derive_output) = + tokio::task::spawn_blocking(move || { + let mut op_block_inputs = vec![]; + let derive_output = derive_machine + .derive(Some(&mut op_block_inputs)) + .expect("could not derive"); + (op_block_inputs, derive_machine, derive_output) + }) + .await?; + + let eth_tail = derive_machine + .derive_input + .db + .get_full_eth_block(derive_output.eth_tail.number) + .context("could not fetch eth tail")? + .block_header + .clone(); + let mut eth_chain = vec![eth_head]; + for block_no in (eth_head_no + 1)..eth_tail.number { + eth_chain.push( + derive_machine + .derive_input + .db + .get_full_eth_block(block_no) + .context("could not fetch eth block")? + .block_header + .clone(), + ); + } + eth_chain.push(eth_tail); + + let (assumptions, bonsai_receipt_uuids, op_block_outputs) = + build_op_blocks(&cli, op_block_inputs).await; + + let derive_input_mem = DeriveInput { + db: derive_machine.derive_input.db.get_mem_db(), + op_head_block_no: core_args.block_number + op_block_index, + op_derive_block_count: composition_size, + op_block_outputs, + block_image_id: OP_BLOCK_ID, + }; info!("Deriving ..."); { - let output_mem = DeriveMachine::new(&OPTIMISM_CHAIN_SPEC, input.clone()) + let input_clone = derive_input_mem.clone(); + let output_mem = tokio::task::spawn_blocking(move || { + DeriveMachine::new( + &OPTIMISM_CHAIN_SPEC, + input_clone, + Some(op_builder_provider_factory), + ) .expect("Could not create derive machine") - .derive() - .context("could not derive")?; - assert_eq!(output, output_mem); + .derive(None) + .context("could not derive") + }) + .await??; + assert_eq!(derive_output, output_mem); } let receipt = maybe_prove( &cli, - &input, + &derive_input_mem, OP_DERIVE_ELF, - &output, - vec![], - file_reference, - Some(&mut receipt_index), - ); + &derive_output, + (assumptions, bonsai_receipt_uuids), + ) + .await; // Append derivation outputs to lift queue - lift_queue.push((output, receipt)); + lift_queue.push((derive_output, receipt)); // Extend block chain - for block in chain { - let tail_num = match eth_chain.last() { + for block in eth_chain { + let tail_num = match complete_eth_chain.last() { None => 0u64, Some(tail) => tail.number, }; // This check should be sufficient if tail_num < block.number { - eth_chain.push(block); + complete_eth_chain.push(block); } } } @@ -319,17 +273,18 @@ pub async fn compose_derived_rollup_blocks( // Prep let mut sibling_map = Default::default(); let mut eth_mountain_range: MerkleMountainRange = Default::default(); - for block in ð_chain { + for block in &complete_eth_chain { eth_mountain_range.append_leaf(block.hash().0, Some(&mut sibling_map)); } let eth_chain_root = eth_mountain_range .root(Some(&mut sibling_map)) .expect("No eth blocks loaded!"); let prep_compose_input = ComposeInput { + block_image_id: OP_BLOCK_ID, derive_image_id: OP_DERIVE_ID, compose_image_id: OP_COMPOSE_ID, operation: ComposeInputOperation::PREP { - eth_blocks: eth_chain, + eth_blocks: complete_eth_chain, prior_prep: None, }, eth_chain_merkle_root: eth_chain_root, @@ -345,16 +300,18 @@ pub async fn compose_derived_rollup_blocks( &prep_compose_input, OP_COMPOSE_ELF, &prep_compose_output, - vec![], - file_reference, - Some(&mut receipt_index), - ); + Default::default(), + ) + .await; // Lift + info!("Lifting {} proofs...", lift_queue.len()); let mut join_queue = VecDeque::new(); for (derive_output, derive_receipt) in lift_queue { let eth_tail_hash = derive_output.eth_tail.hash.0; + trace!("Lifting ... {:?}", &derive_output); let lift_compose_input = ComposeInput { + block_image_id: OP_BLOCK_ID, derive_image_id: OP_DERIVE_ID, compose_image_id: OP_COMPOSE_ID, operation: ComposeInputOperation::LIFT { @@ -363,22 +320,21 @@ pub async fn compose_derived_rollup_blocks( }, eth_chain_merkle_root: eth_chain_root, }; - info!("Lifting ..."); let lift_compose_output = lift_compose_input .clone() .process() .expect("Lift composition failed."); + trace!("Lifted ... {:?}", &lift_compose_output); - let lift_compose_receipt = if let Some(receipt) = derive_receipt { + let lift_compose_receipt = if let Some((receipt_uuid, receipt)) = derive_receipt { maybe_prove( &cli, &lift_compose_input, OP_COMPOSE_ELF, &lift_compose_output, - vec![receipt.into()], - file_reference, - Some(&mut receipt_index), + (vec![receipt.into()], vec![receipt_uuid]), ) + .await } else { None }; @@ -387,9 +343,13 @@ pub async fn compose_derived_rollup_blocks( } // Join + info!("Composing {} proofs...", join_queue.len()); while join_queue.len() > 1 { + // Pop left output let (left, left_receipt) = join_queue.pop_front().unwrap(); + // Only peek at right output let (right, _right_receipt) = join_queue.front().unwrap(); + trace!("Joining"); let ComposeOutputOperation::AGGREGATE { op_tail: left_op_tail, .. @@ -406,37 +366,48 @@ pub async fn compose_derived_rollup_blocks( }; // Push dangling workloads (odd block count) to next round if left_op_tail != right_op_head { + trace!( + "Skipping dangling workload: {} - {}", + left_op_tail.number, + right_op_head.number + ); join_queue.push_back((left, left_receipt)); continue; } - // Pair up join + // Actually pop right output for pairing let (right, right_receipt) = join_queue.pop_front().unwrap(); let join_compose_input = ComposeInput { + block_image_id: OP_BLOCK_ID, derive_image_id: OP_DERIVE_ID, compose_image_id: OP_COMPOSE_ID, operation: ComposeInputOperation::JOIN { left, right }, eth_chain_merkle_root: eth_chain_root, }; - info!("Joining ..."); + trace!("Joining ..."); let join_compose_output = join_compose_input .clone() .process() .expect("Join composition failed."); - let join_compose_receipt = - if let (Some(left_receipt), Some(right_receipt)) = (left_receipt, right_receipt) { - maybe_prove( - &cli, - &join_compose_input, - OP_COMPOSE_ELF, - &join_compose_output, + let join_compose_receipt = if let ( + Some((left_receipt_uuid, left_receipt)), + Some((right_receipt_uuid, right_receipt)), + ) = (left_receipt, right_receipt) + { + maybe_prove( + &cli, + &join_compose_input, + OP_COMPOSE_ELF, + &join_compose_output, + ( vec![left_receipt.into(), right_receipt.into()], - file_reference, - Some(&mut receipt_index), - ) - } else { - None - }; + vec![left_receipt_uuid, right_receipt_uuid], + ), + ) + .await + } else { + None + }; // Send workload to next round join_queue.push_back((join_compose_output, join_compose_receipt)); @@ -445,6 +416,7 @@ pub async fn compose_derived_rollup_blocks( // Finish let (aggregate_output, aggregate_receipt) = join_queue.pop_front().unwrap(); let finish_compose_input = ComposeInput { + block_image_id: OP_BLOCK_ID, derive_image_id: OP_DERIVE_ID, compose_image_id: OP_COMPOSE_ID, operation: ComposeInputOperation::FINISH { @@ -459,30 +431,58 @@ pub async fn compose_derived_rollup_blocks( .process() .expect("Finish composition failed."); - let op_compose_receipt = if let (Some(prep_receipt), Some(aggregate_receipt)) = - (prep_compose_receipt, aggregate_receipt) + if let ( + Some((prep_receipt_uuid, prep_receipt)), + Some((aggregate_receipt_uuid, aggregate_receipt)), + ) = (prep_compose_receipt, aggregate_receipt) { maybe_prove( &cli, &finish_compose_input, OP_COMPOSE_ELF, &finish_compose_output, - vec![prep_receipt.into(), aggregate_receipt.into()], - file_reference, - Some(&mut receipt_index), + ( + vec![prep_receipt.into(), aggregate_receipt.into()], + vec![prep_receipt_uuid, aggregate_receipt_uuid], + ), + ) + .await; + } else if let Cli::Verify(verify_args) = cli { + verify_bonsai_receipt( + OP_COMPOSE_ID.into(), + &finish_compose_output, + verify_args.bonsai_receipt_uuid.clone(), + 4, ) + .await?; } else { - None + info!("Preflight successful!"); }; - dbg!(&finish_compose_output); - - if let Some(final_receipt) = op_compose_receipt { - final_receipt - .verify(OP_COMPOSE_ID) - .expect("Failed to verify final receipt"); - info!("Verified final receipt!"); - } + trace!("Final composition output: {:?}", &finish_compose_output); Ok(()) } + +async fn build_op_blocks( + cli: &Cli, + op_block_inputs: Vec>, +) -> (Vec, Vec, Vec) { + let mut assumptions: Vec = vec![]; + let mut bonsai_uuids = vec![]; + let mut op_block_outputs = vec![]; + for input in op_block_inputs { + let output = OptimismStrategy::build_from(&OP_MAINNET_CHAIN_SPEC, input.clone()) + .expect("Failed to build op block") + .with_state_hashed(); + + if let Some((bonsai_receipt_uuid, receipt)) = + maybe_prove(cli, &input, OP_BLOCK_ELF, &output, Default::default()).await + { + assumptions.push(receipt.into()); + bonsai_uuids.push(bonsai_receipt_uuid); + } + op_block_outputs.push(output); + } + (assumptions, bonsai_uuids, op_block_outputs) +} diff --git a/host/testdata/derivation/ethereum/18090206.json.gz b/host/testdata/derivation/ethereum/18090206.json.gz index da043287..33322084 100644 Binary files a/host/testdata/derivation/ethereum/18090206.json.gz and b/host/testdata/derivation/ethereum/18090206.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090207.json.gz b/host/testdata/derivation/ethereum/18090207.json.gz index d6b69373..c3635dba 100644 Binary files a/host/testdata/derivation/ethereum/18090207.json.gz and b/host/testdata/derivation/ethereum/18090207.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090208.json.gz b/host/testdata/derivation/ethereum/18090208.json.gz index 1e886d15..80bd7e9f 100644 Binary files a/host/testdata/derivation/ethereum/18090208.json.gz and b/host/testdata/derivation/ethereum/18090208.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090209.json.gz b/host/testdata/derivation/ethereum/18090209.json.gz index 88cd5f04..d7c49ae0 100644 Binary files a/host/testdata/derivation/ethereum/18090209.json.gz and b/host/testdata/derivation/ethereum/18090209.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090210.json.gz b/host/testdata/derivation/ethereum/18090210.json.gz index d39fe8bc..d60a44cd 100644 Binary files a/host/testdata/derivation/ethereum/18090210.json.gz and b/host/testdata/derivation/ethereum/18090210.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090211.json.gz b/host/testdata/derivation/ethereum/18090211.json.gz index 5cd54573..10e0f035 100644 Binary files a/host/testdata/derivation/ethereum/18090211.json.gz and b/host/testdata/derivation/ethereum/18090211.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090212.json.gz b/host/testdata/derivation/ethereum/18090212.json.gz index d46eca5d..6c720764 100644 Binary files a/host/testdata/derivation/ethereum/18090212.json.gz and b/host/testdata/derivation/ethereum/18090212.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090213.json.gz b/host/testdata/derivation/ethereum/18090213.json.gz index de28d0c1..b953031d 100644 Binary files a/host/testdata/derivation/ethereum/18090213.json.gz and b/host/testdata/derivation/ethereum/18090213.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090214.json.gz b/host/testdata/derivation/ethereum/18090214.json.gz index b4f6249b..c77cb194 100644 Binary files a/host/testdata/derivation/ethereum/18090214.json.gz and b/host/testdata/derivation/ethereum/18090214.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090215.json.gz b/host/testdata/derivation/ethereum/18090215.json.gz index 72ead9d2..fff3b013 100644 Binary files a/host/testdata/derivation/ethereum/18090215.json.gz and b/host/testdata/derivation/ethereum/18090215.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090216.json.gz b/host/testdata/derivation/ethereum/18090216.json.gz index c25ee505..0ea65cd8 100644 Binary files a/host/testdata/derivation/ethereum/18090216.json.gz and b/host/testdata/derivation/ethereum/18090216.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090217.json.gz b/host/testdata/derivation/ethereum/18090217.json.gz index 7b03884b..67abe012 100644 Binary files a/host/testdata/derivation/ethereum/18090217.json.gz and b/host/testdata/derivation/ethereum/18090217.json.gz differ diff --git a/host/testdata/derivation/ethereum/18090218.json.gz b/host/testdata/derivation/ethereum/18090218.json.gz index 899286e0..cc0eb42b 100644 Binary files a/host/testdata/derivation/ethereum/18090218.json.gz and b/host/testdata/derivation/ethereum/18090218.json.gz differ diff --git a/host/testdata/derivation/optimism/109279674.json.gz b/host/testdata/derivation/optimism/109279674.json.gz index 1fc93512..ebd22b78 100644 Binary files a/host/testdata/derivation/optimism/109279674.json.gz and b/host/testdata/derivation/optimism/109279674.json.gz differ diff --git a/host/testdata/derivation/optimism/109279675.json.gz b/host/testdata/derivation/optimism/109279675.json.gz index e8b9341e..caeed4b9 100644 Binary files a/host/testdata/derivation/optimism/109279675.json.gz and b/host/testdata/derivation/optimism/109279675.json.gz differ diff --git a/host/testdata/derivation/optimism/109279676.json.gz b/host/testdata/derivation/optimism/109279676.json.gz index 3089101f..af3eb10b 100644 Binary files a/host/testdata/derivation/optimism/109279676.json.gz and b/host/testdata/derivation/optimism/109279676.json.gz differ diff --git a/host/testdata/derivation/optimism/109279677.json.gz b/host/testdata/derivation/optimism/109279677.json.gz index bdc52000..cab3f9ca 100644 Binary files a/host/testdata/derivation/optimism/109279677.json.gz and b/host/testdata/derivation/optimism/109279677.json.gz differ diff --git a/host/testdata/derivation/optimism/109279678.json.gz b/host/testdata/derivation/optimism/109279678.json.gz index cd4e0b97..ef2c4a91 100644 Binary files a/host/testdata/derivation/optimism/109279678.json.gz and b/host/testdata/derivation/optimism/109279678.json.gz differ diff --git a/host/testdata/derivation/optimism/109279679.json.gz b/host/testdata/derivation/optimism/109279679.json.gz index fcd78d79..218fdb29 100644 Binary files a/host/testdata/derivation/optimism/109279679.json.gz and b/host/testdata/derivation/optimism/109279679.json.gz differ diff --git a/host/testdata/derivation/optimism/109279680.json.gz b/host/testdata/derivation/optimism/109279680.json.gz index 02a37308..2b61cc5f 100644 Binary files a/host/testdata/derivation/optimism/109279680.json.gz and b/host/testdata/derivation/optimism/109279680.json.gz differ diff --git a/lib/Cargo.toml b/lib/Cargo.toml index 25ebf9d8..c94111e5 100644 --- a/lib/Cargo.toml +++ b/lib/Cargo.toml @@ -4,8 +4,16 @@ version = "0.1.0" edition = "2021" [dependencies] +alloy-primitives = { version = "0.6.2", default-features = false, features = [ + "rlp", + "serde", + "std", +] } +alloy-rlp = { version = "0.3", default-features = false } +alloy-rlp-derive = { version = "0.3", default-features = false } alloy-sol-types = "0.6" anyhow = "1.0" +bincode = "1.3" bytes = "1.5" ethers-core = { version = "2.0", features = ["optimism"] } hashbrown = { workspace = true } diff --git a/lib/src/builder/execute/ethereum.rs b/lib/src/builder/execute/ethereum.rs index c8cc58b0..7ee4cd1f 100644 --- a/lib/src/builder/execute/ethereum.rs +++ b/lib/src/builder/execute/ethereum.rs @@ -16,7 +16,7 @@ use core::{fmt::Debug, mem::take}; use anyhow::{anyhow, bail, Context}; #[cfg(not(target_os = "zkvm"))] -use log::debug; +use log::trace; use revm::{ interpreter::Host, primitives::{Account, Address, ResultAndState, SpecId, TransactTo, TxEnv}, @@ -24,13 +24,14 @@ use revm::{ }; use ruint::aliases::U256; use zeth_primitives::{ + alloy_rlp, receipt::Receipt, transactions::{ ethereum::{EthereumTxEssence, TransactionKind}, TxEssence, }, trie::MptNode, - Bloom, RlpBytes, + Bloom, }; use super::TxExecStrategy; @@ -56,30 +57,48 @@ impl TxExecStrategy for EthTxExecStrategy { // Compute the spec id let spec_id = block_builder.chain_spec.spec_id(header.number); if !SpecId::enabled(spec_id, MIN_SPEC_ID) { - bail!( + panic!( "Invalid protocol version: expected >= {:?}, got {:?}", - MIN_SPEC_ID, - spec_id, + MIN_SPEC_ID, spec_id, ) } #[cfg(not(target_os = "zkvm"))] { use chrono::{TimeZone, Utc}; - use log::info; let dt = Utc - .timestamp_opt(block_builder.input.timestamp.try_into().unwrap(), 0) + .timestamp_opt( + block_builder + .input + .state_input + .timestamp + .try_into() + .unwrap(), + 0, + ) .unwrap(); - info!("Block no. {}", header.number); - info!(" EVM spec ID: {:?}", spec_id); - info!(" Timestamp: {}", dt); - info!(" Transactions: {}", block_builder.input.transactions.len()); - info!(" Withdrawals: {}", block_builder.input.withdrawals.len()); - info!(" Fee Recipient: {:?}", block_builder.input.beneficiary); - info!(" Gas limit: {}", block_builder.input.gas_limit); - info!(" Base fee per gas: {}", header.base_fee_per_gas); - info!(" Extra data: {:?}", block_builder.input.extra_data); + trace!("Block no. {}", header.number); + trace!(" EVM spec ID: {:?}", spec_id); + trace!(" Timestamp: {}", dt); + trace!( + " Transactions: {}", + block_builder.input.state_input.transactions.len() + ); + trace!( + " Withdrawals: {}", + block_builder.input.state_input.withdrawals.len() + ); + trace!( + " Fee Recipient: {:?}", + 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 + ); } // initialize the Evm @@ -93,12 +112,12 @@ impl TxExecStrategy for EthTxExecStrategy { .modify_block_env(|blk_env| { // set the EVM block environment blk_env.number = header.number.try_into().unwrap(); - blk_env.coinbase = block_builder.input.beneficiary; + blk_env.coinbase = block_builder.input.state_input.beneficiary; blk_env.timestamp = 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.gas_limit; + blk_env.gas_limit = block_builder.input.state_input.gas_limit; }) .with_db(block_builder.db.take().unwrap()) .build(); @@ -111,7 +130,7 @@ impl TxExecStrategy for EthTxExecStrategy { // process all the transactions let mut tx_trie = MptNode::default(); let mut receipt_trie = MptNode::default(); - for (tx_no, tx) in take(&mut block_builder.input.transactions) + for (tx_no, tx) in take(&mut block_builder.input.state_input.transactions) .into_iter() .enumerate() { @@ -123,14 +142,15 @@ impl TxExecStrategy for EthTxExecStrategy { #[cfg(not(target_os = "zkvm"))] { let tx_hash = tx.hash(); - debug!("Tx no. {} (hash: {})", tx_no, tx_hash); - debug!(" Type: {}", tx.essence.tx_type()); - debug!(" Fr: {:?}", tx_from); - debug!(" To: {:?}", tx.essence.to().unwrap_or_default()); + trace!("Tx no. {} (hash: {})", tx_no, tx_hash); + trace!(" Type: {}", tx.essence.tx_type()); + trace!(" Fr: {:?}", tx_from); + trace!(" To: {:?}", tx.essence.to().unwrap_or_default()); } // verify transaction gas - let block_available_gas = block_builder.input.gas_limit - cumulative_gas_used; + let block_available_gas = + block_builder.input.state_input.gas_limit - cumulative_gas_used; if block_available_gas < tx.essence.gas_limit() { bail!("Error at transaction {}: gas exceeds block limit", tx_no); } @@ -139,13 +159,15 @@ impl TxExecStrategy for EthTxExecStrategy { fill_eth_tx_env(&mut evm.env().tx, &tx.essence, tx_from); let ResultAndState { result, state } = evm .transact() - .map_err(|evm_err| anyhow!("Error at transaction {}: {:?}", tx_no, evm_err))?; + .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."); let gas_used = result.gas_used().try_into().unwrap(); cumulative_gas_used = cumulative_gas_used.checked_add(gas_used).unwrap(); #[cfg(not(target_os = "zkvm"))] - debug!(" Ok: {:?}", result); + trace!(" Ok: {:?}", result); // create the receipt from the EVM result let receipt = Receipt::new( @@ -159,20 +181,22 @@ impl TxExecStrategy for EthTxExecStrategy { logs_bloom.accrue_bloom(&receipt.payload.logs_bloom); // Add receipt and tx to tries - let trie_key = tx_no.to_rlp(); + let trie_key = alloy_rlp::encode(tx_no); tx_trie .insert_rlp(&trie_key, tx) - .context("failed to insert transaction")?; + // todo: change unrecoverable panic to host-side recoverable `Result` + .expect("failed to insert transaction"); receipt_trie .insert_rlp(&trie_key, receipt) - .context("failed to insert receipt")?; + // todo: change unrecoverable panic to host-side recoverable `Result` + .expect("failed to insert receipt"); // update account states #[cfg(not(target_os = "zkvm"))] for (address, account) in &state { if account.is_touched() { // log account - debug!( + trace!( " State {:?} (is_selfdestructed={}, is_loaded_as_not_existing={}, is_created={}, is_empty={})", address, account.is_selfdestructed(), @@ -181,17 +205,18 @@ impl TxExecStrategy for EthTxExecStrategy { account.is_empty(), ); // log balance changes - debug!( + trace!( " After balance: {} (Nonce: {})", - account.info.balance, account.info.nonce + account.info.balance, + account.info.nonce ); // log state changes for (addr, slot) in &account.storage { if slot.is_changed() { - debug!(" Storage address: {:?}", addr); - debug!(" Before: {:?}", slot.original_value()); - debug!(" After: {:?}", slot.present_value()); + trace!(" Storage address: {:?}", addr); + trace!(" Before: {:?}", slot.original_value()); + trace!(" After: {:?}", slot.present_value()); } } } @@ -202,7 +227,7 @@ impl TxExecStrategy for EthTxExecStrategy { // process withdrawals unconditionally after any transactions let mut withdrawals_trie = MptNode::default(); - for (i, withdrawal) in take(&mut block_builder.input.withdrawals) + for (i, withdrawal) in take(&mut block_builder.input.state_input.withdrawals) .into_iter() .enumerate() { @@ -213,16 +238,19 @@ impl TxExecStrategy for EthTxExecStrategy { #[cfg(not(target_os = "zkvm"))] { - debug!("Withdrawal no. {}", withdrawal.index); - debug!(" Recipient: {:?}", withdrawal.address); - debug!(" Value: {}", amount_wei); + trace!("Withdrawal no. {}", withdrawal.index); + trace!(" Recipient: {:?}", withdrawal.address); + trace!(" Value: {}", amount_wei); } // Credit withdrawal amount - increase_account_balance(&mut evm.context.evm.db, withdrawal.address, amount_wei)?; + increase_account_balance(&mut evm.context.evm.db, withdrawal.address, amount_wei) + // todo: change unrecoverable panic to host-side recoverable `Result` + .expect("Failed to increase account balance."); // Add withdrawal to trie withdrawals_trie - .insert_rlp(&i.to_rlp(), withdrawal) - .context("failed to insert withdrawal")?; + .insert_rlp(&alloy_rlp::encode(i), withdrawal) + // todo: change unrecoverable panic to host-side recoverable `Result` + .expect("failed to insert withdrawal"); } // Update result header with computed values diff --git a/lib/src/builder/execute/optimism.rs b/lib/src/builder/execute/optimism.rs index da6c31df..2ef5304b 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::debug; +use log::trace; use revm::{ interpreter::Host, optimism, @@ -25,6 +25,7 @@ use revm::{ }; use ruint::aliases::U256; use zeth_primitives::{ + alloy_rlp, receipt::Receipt, transactions::{ ethereum::{EthereumTxEssence, TransactionKind}, @@ -32,7 +33,7 @@ use zeth_primitives::{ TxEssence, }, trie::MptNode, - Bloom, Bytes, RlpBytes, + Bloom, Bytes, }; use super::{ethereum, TxExecStrategy}; @@ -58,10 +59,9 @@ impl TxExecStrategy for OpTxExecStrategy { // Compute the spec id let spec_id = block_builder.chain_spec.spec_id(header.number); if !SpecId::enabled(spec_id, MIN_SPEC_ID) { - bail!( + panic!( "Invalid protocol version: expected >= {:?}, got {:?}", - MIN_SPEC_ID, - spec_id, + MIN_SPEC_ID, spec_id, ) } let chain_id = block_builder.chain_spec.chain_id(); @@ -69,19 +69,35 @@ impl TxExecStrategy for OpTxExecStrategy { #[cfg(not(target_os = "zkvm"))] { use chrono::{TimeZone, Utc}; - use log::info; let dt = Utc - .timestamp_opt(block_builder.input.timestamp.try_into().unwrap(), 0) + .timestamp_opt( + block_builder + .input + .state_input + .timestamp + .try_into() + .unwrap(), + 0, + ) .unwrap(); - info!("Block no. {}", header.number); - info!(" EVM spec ID: {:?}", spec_id); - info!(" Timestamp: {}", dt); - info!(" Transactions: {}", block_builder.input.transactions.len()); - info!(" Fee Recipient: {:?}", block_builder.input.beneficiary); - info!(" Gas limit: {}", block_builder.input.gas_limit); - info!(" Base fee per gas: {}", header.base_fee_per_gas); - info!(" Extra data: {:?}", block_builder.input.extra_data); + trace!("Block no. {}", header.number); + trace!(" EVM spec ID: {:?}", spec_id); + trace!(" Timestamp: {}", dt); + trace!( + " Transactions: {}", + block_builder.input.state_input.transactions.len() + ); + trace!( + " Fee Recipient: {:?}", + 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 + ); } let mut evm = Evm::builder() @@ -94,12 +110,12 @@ impl TxExecStrategy for OpTxExecStrategy { .modify_block_env(|blk_env| { // set the EVM block environment blk_env.number = header.number.try_into().unwrap(); - blk_env.coinbase = block_builder.input.beneficiary; + blk_env.coinbase = block_builder.input.state_input.beneficiary; blk_env.timestamp = 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.gas_limit; + blk_env.gas_limit = block_builder.input.state_input.gas_limit; }) .with_db(block_builder.db.take().unwrap()) .append_handler_register(optimism::optimism_handle_register) @@ -113,7 +129,7 @@ impl TxExecStrategy for OpTxExecStrategy { // process all the transactions let mut tx_trie = MptNode::default(); let mut receipt_trie = MptNode::default(); - for (tx_no, tx) in take(&mut block_builder.input.transactions) + for (tx_no, tx) in take(&mut block_builder.input.state_input.transactions) .into_iter() .enumerate() { @@ -125,14 +141,15 @@ impl TxExecStrategy for OpTxExecStrategy { #[cfg(not(target_os = "zkvm"))] { let tx_hash = tx.hash(); - debug!("Tx no. {} (hash: {})", tx_no, tx_hash); - debug!(" Type: {}", tx.essence.tx_type()); - debug!(" Fr: {:?}", tx_from); - debug!(" To: {:?}", tx.essence.to().unwrap_or_default()); + trace!("Tx no. {} (hash: {})", tx_no, tx_hash); + trace!(" Type: {}", tx.essence.tx_type()); + trace!(" Fr: {:?}", tx_from); + trace!(" To: {:?}", tx.essence.to().unwrap_or_default()); } // verify transaction gas - let block_available_gas = block_builder.input.gas_limit - cumulative_gas_used; + let block_available_gas = + block_builder.input.state_input.gas_limit - cumulative_gas_used; if block_available_gas < tx.essence.gas_limit() { bail!("Error at transaction {}: gas exceeds block limit", tx_no); } @@ -141,29 +158,31 @@ impl TxExecStrategy for OpTxExecStrategy { OptimismTxEssence::OptimismDeposited(deposit) => { #[cfg(not(target_os = "zkvm"))] { - debug!(" Source: {:?}", &deposit.source_hash); - debug!(" Mint: {:?}", &deposit.mint); - debug!(" System Tx: {:?}", deposit.is_system_tx); + trace!(" Source: {:?}", &deposit.source_hash); + trace!(" Mint: {:?}", &deposit.mint); + trace!(" System Tx: {:?}", deposit.is_system_tx); } // Initialize tx environment fill_deposit_tx_env(&mut evm.env().tx, deposit, tx_from); } OptimismTxEssence::Ethereum(essence) => { - fill_eth_tx_env(&mut evm.env().tx, tx.to_rlp(), essence, tx_from); + fill_eth_tx_env(&mut evm.env().tx, alloy_rlp::encode(&tx), essence, tx_from); } }; // process the transaction let ResultAndState { result, state } = evm .transact() - .map_err(|evm_err| anyhow!("Error at transaction {}: {:?}", tx_no, evm_err))?; + .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."); let gas_used = result.gas_used().try_into().unwrap(); cumulative_gas_used = cumulative_gas_used.checked_add(gas_used).unwrap(); #[cfg(not(target_os = "zkvm"))] - debug!(" Ok: {:?}", result); + trace!(" Ok: {:?}", result); // create the receipt from the EVM result let receipt = Receipt::new( @@ -178,7 +197,7 @@ impl TxExecStrategy for OpTxExecStrategy { for (address, account) in &state { if account.is_touched() { // log account - debug!( + trace!( " State {:?} (is_selfdestructed={}, is_loaded_as_not_existing={}, is_created={})", address, account.is_selfdestructed(), @@ -186,17 +205,18 @@ impl TxExecStrategy for OpTxExecStrategy { account.is_created() ); // log balance changes - debug!( + trace!( " After balance: {} (Nonce: {})", - account.info.balance, account.info.nonce + account.info.balance, + account.info.nonce ); // log state changes for (addr, slot) in &account.storage { if slot.is_changed() { - debug!(" Storage address: {:?}", addr); - debug!(" Before: {:?}", slot.original_value()); - debug!(" After: {:?}", slot.present_value()); + trace!(" Storage address: {:?}", addr); + trace!(" Before: {:?}", slot.original_value()); + trace!(" After: {:?}", slot.present_value()); } } } @@ -208,13 +228,15 @@ impl TxExecStrategy for OpTxExecStrategy { logs_bloom.accrue_bloom(&receipt.payload.logs_bloom); // Add receipt and tx to tries - let trie_key = tx_no.to_rlp(); + let trie_key = alloy_rlp::encode(tx_no); tx_trie .insert_rlp(&trie_key, tx) - .context("failed to insert transaction")?; + // todo: change unrecoverable panic to host-side recoverable `Result` + .expect("failed to insert transaction"); receipt_trie .insert_rlp(&trie_key, receipt) - .context("failed to insert receipt")?; + // todo: change unrecoverable panic to host-side recoverable `Result` + .expect("failed to insert receipt"); } // Update result header with computed values diff --git a/lib/src/builder/initialize.rs b/lib/src/builder/initialize.rs index 8b409b79..6a3fc26e 100644 --- a/lib/src/builder/initialize.rs +++ b/lib/src/builder/initialize.rs @@ -52,11 +52,11 @@ impl DbInitStrategy for MemDbInitStrategy { ) -> Result> { // Verify state trie root if block_builder.input.parent_state_trie.hash() - != block_builder.input.parent_header.state_root + != block_builder.input.state_input.parent_header.state_root { bail!( "Invalid state trie: expected {}, got {}", - block_builder.input.parent_header.state_root, + block_builder.input.state_input.parent_header.state_root, block_builder.input.parent_state_trie.hash() ); } @@ -126,10 +126,10 @@ impl DbInitStrategy for MemDbInitStrategy { let mut block_hashes = HashMap::with_capacity(block_builder.input.ancestor_headers.len() + 1); block_hashes.insert( - block_builder.input.parent_header.number, - block_builder.input.parent_header.hash(), + block_builder.input.state_input.parent_header.number, + block_builder.input.state_input.parent_header.hash(), ); - let mut prev = &block_builder.input.parent_header; + let mut prev = &block_builder.input.state_input.parent_header; for current in &block_builder.input.ancestor_headers { let current_hash = current.hash(); if prev.parent_hash != current_hash { @@ -139,8 +139,9 @@ impl DbInitStrategy for MemDbInitStrategy { prev.number ); } - if block_builder.input.parent_header.number < current.number - || block_builder.input.parent_header.number - current.number >= MAX_BLOCK_HASH_AGE + if block_builder.input.state_input.parent_header.number < current.number + || block_builder.input.state_input.parent_header.number - current.number + >= MAX_BLOCK_HASH_AGE { bail!( "Invalid chain: {} is not one of the {} most recent blocks", diff --git a/lib/src/builder/mod.rs b/lib/src/builder/mod.rs index 7763b803..9eb44c03 100644 --- a/lib/src/builder/mod.rs +++ b/lib/src/builder/mod.rs @@ -12,8 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. +#[cfg(not(target_os = "zkvm"))] +use std::sync::{Arc, Mutex}; + use anyhow::Result; use revm::{Database, DatabaseCommit}; +use serde::Serialize; use zeth_primitives::{ block::Header, transactions::{ethereum::EthereumTxEssence, optimism::OptimismTxEssence, TxEssence}, @@ -28,8 +32,9 @@ use crate::{ prepare::{EthHeaderPrepStrategy, HeaderPrepStrategy}, }, consts::ChainSpec, - input::Input, + input::BlockBuildInput, mem_db::MemDb, + output::BlockBuildOutput, }; mod execute; @@ -37,13 +42,33 @@ mod finalize; mod initialize; mod prepare; +#[cfg(not(target_os = "zkvm"))] +type DatabaseRescue = Arc>>; +#[cfg(target_os = "zkvm")] +type DatabaseRescue = core::marker::PhantomData; + /// A generic builder for building a block. #[derive(Clone, Debug)] pub struct BlockBuilder<'a, D, E: TxEssence> { pub(crate) chain_spec: &'a ChainSpec, - pub(crate) input: Input, + pub(crate) input: BlockBuildInput, pub(crate) db: Option, pub(crate) header: Option
, + pub db_drop_destination: Option>, +} + +// 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> { + fn drop(&mut self) { + if let Some(backup_target) = &mut self.db_drop_destination { + if let Some(dropped_db) = self.db.take() { + if let Ok(mut target_option) = backup_target.lock() { + target_option.replace(dropped_db); + } + } + } + } } impl BlockBuilder<'_, D, E> @@ -53,12 +78,17 @@ where E: TxEssence, { /// Creates a new block builder. - pub fn new(chain_spec: &ChainSpec, input: Input) -> BlockBuilder<'_, D, E> { + pub fn new( + chain_spec: &ChainSpec, + input: BlockBuildInput, + db_backup: Option>, + ) -> BlockBuilder<'_, D, E> { BlockBuilder { chain_spec, db: None, header: None, input, + db_drop_destination: db_backup, } } @@ -97,11 +127,16 @@ where pub fn mut_db(&mut self) -> Option<&mut D> { self.db.as_mut() } + + /// Destroys the builder and returns the database + pub fn take_db(mut self) -> Option { + self.db.take() + } } /// A bundle of strategies for building a block using [BlockBuilder]. pub trait BlockBuilderStrategy { - type TxEssence: TxEssence; + type TxEssence: TxEssence + Serialize; type DbInitStrategy: DbInitStrategy; type HeaderPrepStrategy: HeaderPrepStrategy; @@ -111,13 +146,45 @@ pub trait BlockBuilderStrategy { /// Builds a block from the given input. fn build_from( chain_spec: &ChainSpec, - input: Input, - ) -> Result<(Header, MptNode)> { - BlockBuilder::::new(chain_spec, input) - .initialize_database::()? - .prepare_header::()? - .execute_transactions::()? - .finalize::() + input: BlockBuildInput, + ) -> Result { + // todo: compute `input_hash` only on build error + let input_hash = input.state_input.hash(); + + let builder = BlockBuilder::::new(chain_spec, input, None); + + // Database initialization errors do not indicate a faulty block + let initialized = builder.initialize_database::()?; + + // Recoverable header validation errors mean a faulty block + let prepared = match initialized.prepare_header::() { + Ok(builder) => builder, + Err(_) => { + return Ok(BlockBuildOutput::FAILURE { + state_input_hash: input_hash.into(), + }) + } + }; + + // Recoverable transaction execution errors mean a faulty block + let executed = match prepared.execute_transactions::() { + Ok(builder) => builder, + Err(_) => { + return Ok(BlockBuildOutput::FAILURE { + state_input_hash: input_hash.into(), + }) + } + }; + + // Finalization errors do not indicate a faulty block + let (header, state) = executed.finalize::()?; + + Ok(BlockBuildOutput::SUCCESS { + hash: header.hash(), + head: header, + state, + state_input_hash: input_hash.into(), + }) } } diff --git a/lib/src/builder/prepare.rs b/lib/src/builder/prepare.rs index 24314304..6cf62c57 100644 --- a/lib/src/builder/prepare.rs +++ b/lib/src/builder/prepare.rs @@ -43,35 +43,39 @@ impl HeaderPrepStrategy for EthHeaderPrepStrategy { // Validate gas limit let diff = block_builder .input + .state_input .parent_header .gas_limit - .abs_diff(block_builder.input.gas_limit); - let limit = block_builder.input.parent_header.gas_limit / GAS_LIMIT_BOUND_DIVISOR; + .abs_diff(block_builder.input.state_input.gas_limit); + let limit = + block_builder.input.state_input.parent_header.gas_limit / GAS_LIMIT_BOUND_DIVISOR; if diff >= limit { bail!( "Invalid gas limit: expected {} +- {}, got {}", - block_builder.input.parent_header.gas_limit, + block_builder.input.state_input.parent_header.gas_limit, limit, - block_builder.input.gas_limit, + block_builder.input.state_input.gas_limit, ); } - if block_builder.input.gas_limit < MIN_GAS_LIMIT { + if block_builder.input.state_input.gas_limit < MIN_GAS_LIMIT { bail!( "Invalid gas limit: expected >= {}, got {}", MIN_GAS_LIMIT, - block_builder.input.gas_limit, + block_builder.input.state_input.gas_limit, ); } // Validate timestamp - if block_builder.input.timestamp <= block_builder.input.parent_header.timestamp { + if block_builder.input.state_input.timestamp + <= block_builder.input.state_input.parent_header.timestamp + { bail!( "Invalid timestamp: expected > {}, got {}", - block_builder.input.parent_header.timestamp, - block_builder.input.timestamp, + block_builder.input.state_input.parent_header.timestamp, + block_builder.input.state_input.timestamp, ); } // Validate extra data - let extra_data_bytes = block_builder.input.extra_data.len(); + let extra_data_bytes = block_builder.input.state_input.extra_data.len(); if extra_data_bytes > MAX_EXTRA_DATA_BYTES { bail!( "Invalid extra data: expected <= {}, got {}", @@ -82,23 +86,24 @@ impl HeaderPrepStrategy for EthHeaderPrepStrategy { // Derive header block_builder.header = Some(Header { // Initialize fields that we can compute from the parent - parent_hash: block_builder.input.parent_header.hash(), + 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.parent_header, + &block_builder.input.state_input.parent_header, block_builder.chain_spec.gas_constants(), - )?, + ), // Initialize metadata from input - beneficiary: block_builder.input.beneficiary, - gas_limit: block_builder.input.gas_limit, - timestamp: block_builder.input.timestamp, - mix_hash: block_builder.input.mix_hash, - extra_data: block_builder.input.extra_data.clone(), + beneficiary: block_builder.input.state_input.beneficiary, + gas_limit: block_builder.input.state_input.gas_limit, + timestamp: block_builder.input.state_input.timestamp, + mix_hash: block_builder.input.state_input.mix_hash, + extra_data: block_builder.input.state_input.extra_data.clone(), // do not fill the remaining fields ..Default::default() }); @@ -107,11 +112,11 @@ 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) -> Result { +fn derive_base_fee(parent: &Header, eip_1559_constants: &Eip1559Constants) -> U256 { let parent_gas_target = parent.gas_limit / eip_1559_constants.elasticity_multiplier; match parent.gas_used.cmp(&parent_gas_target) { - std::cmp::Ordering::Equal => Ok(parent.base_fee_per_gas), + std::cmp::Ordering::Equal => parent.base_fee_per_gas, std::cmp::Ordering::Greater => { let gas_used_delta = parent.gas_used - parent_gas_target; @@ -124,7 +129,7 @@ fn derive_base_fee(parent: &Header, eip_1559_constants: &Eip1559Constants) -> Re .min( parent.base_fee_per_gas / eip_1559_constants.base_fee_max_increase_denominator, ); - Ok(parent.base_fee_per_gas + base_fee_delta) + parent.base_fee_per_gas + base_fee_delta } std::cmp::Ordering::Less => { @@ -135,7 +140,7 @@ fn derive_base_fee(parent: &Header, eip_1559_constants: &Eip1559Constants) -> Re .min( parent.base_fee_per_gas / eip_1559_constants.base_fee_max_decrease_denominator, ); - Ok(parent.base_fee_per_gas - base_fee_delta) + parent.base_fee_per_gas - base_fee_delta } } } diff --git a/lib/src/host/mod.rs b/lib/src/host/mod.rs index c75d65d3..5208be3f 100644 --- a/lib/src/host/mod.rs +++ b/lib/src/host/mod.rs @@ -12,9 +12,48 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::path::{Path, PathBuf}; + +use crate::{ + consts::Network, + host::provider::{new_provider, Provider}, +}; + pub mod mpt; pub mod preflight; pub mod provider; pub mod provider_db; pub mod rpc_db; pub mod verify; + +pub fn cache_file_path(cache_path: &Path, network: &str, block_no: u64, ext: &str) -> PathBuf { + cache_path + .join(network) + .join(block_no.to_string()) + .with_extension(ext) +} + +#[derive(Clone)] +pub struct ProviderFactory { + pub dir: Option, + pub network: Network, + pub rpc_url: Option, +} + +impl ProviderFactory { + pub fn new(dir: Option, network: Network, rpc_url: Option) -> Self { + Self { + dir, + network, + rpc_url, + } + } + + pub fn create_provider(&self, block_number: u64) -> anyhow::Result> { + let rpc_cache = self + .dir + .as_ref() + .map(|dir| cache_file_path(dir, &self.network.to_string(), block_number, "json.gz")); + new_provider(rpc_cache, self.rpc_url.clone()) + } +} diff --git a/lib/src/host/preflight.rs b/lib/src/host/preflight.rs index 91c1aff1..d47a937b 100644 --- a/lib/src/host/preflight.rs +++ b/lib/src/host/preflight.rs @@ -12,20 +12,24 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::{fmt::Debug, path::PathBuf}; +use std::{ + fmt::Debug, + path::PathBuf, + sync::{Arc, Mutex}, +}; use anyhow::{anyhow, Context, Result}; use ethers_core::types::{ Block as EthersBlock, EIP1186ProofResponse, Transaction as EthersTransaction, }; use hashbrown::{HashMap, HashSet}; -use log::info; +use log::{debug, info}; use zeth_primitives::{ block::Header, ethers::{from_ethers_h160, from_ethers_h256, from_ethers_u256}, keccak::keccak, transactions::{Transaction, TxEssence}, - trie::{MptNode, MptNodeData, MptNodeReference, EMPTY_ROOT}, + trie::{MptNode, MptNodeReference}, withdrawal::Withdrawal, Address, B256, U256, }; @@ -38,7 +42,7 @@ use crate::{ provider::{new_provider, BlockQuery}, provider_db::ProviderDb, }, - input::{Input, StorageEntry}, + input::{BlockBuildInput, StateInput, StorageEntry}, mem_db::MemDb, }; @@ -48,7 +52,7 @@ pub struct Data { pub db: MemDb, pub parent_header: Header, pub parent_proofs: HashMap, - pub header: Header, + pub header: Option
, pub transactions: Vec>, pub withdrawals: Vec, pub proofs: HashMap, @@ -58,12 +62,18 @@ pub struct Data { 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 run_preflight( + fn preflight_with_external_data( chain_spec: ChainSpec, cache_path: Option, rpc_url: Option, block_no: u64, ) -> Result>; + + fn preflight_with_local_data( + chain_spec: ChainSpec, + provider_db: ProviderDb, + input: BlockBuildInput, + ) -> Result>; } /// Implements the [Preflight] trait for all compatible [BlockBuilderStrategy]s. @@ -72,7 +82,7 @@ where N::TxEssence: TryFrom, >::Error: Debug, { - fn run_preflight( + fn preflight_with_external_data( chain_spec: ChainSpec, cache_path: Option, rpc_url: Option, @@ -85,7 +95,7 @@ where block_no: block_no - 1, })?; - info!( + debug!( "Initial block: {:?} ({:?})", parent_block.number.unwrap(), parent_block.hash.unwrap() @@ -95,27 +105,47 @@ where // Fetch the target block let block = provider.get_full_block(&BlockQuery { block_no })?; - info!( + debug!( "Final block number: {:?} ({:?})", block.number.unwrap(), block.hash.unwrap() ); - info!("Transaction count: {:?}", block.transactions.len()); + debug!("Transaction count: {:?}", block.transactions.len()); // Create the provider DB let provider_db = ProviderDb::new(provider, parent_header.number); // Create the input data let input = new_preflight_input(block.clone(), parent_header.clone())?; - let transactions = input.transactions.clone(); - let withdrawals = input.withdrawals.clone(); // Create the block builder, run the transactions and extract the DB - let mut builder = BlockBuilder::new(&chain_spec, input) - .with_db(provider_db) - .prepare_header::()? - .execute_transactions::()?; - let provider_db = builder.mut_db().unwrap(); + 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 + }, + ) + } + + fn preflight_with_local_data( + chain_spec: ChainSpec, + provider_db: ProviderDb, + 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(); + // Create the block builder, run the transactions and extract the DB even if run fails + let db_backup = Arc::new(Mutex::new(None)); + let builder = + BlockBuilder::new(&chain_spec, input, Some(db_backup.clone())).with_db(provider_db); + let mut provider_db = match builder.prepare_header::() { + Ok(builder) => match builder.execute_transactions::() { + Ok(builder) => builder.take_db().unwrap(), + Err(_) => db_backup.lock().unwrap().take().unwrap(), + }, + Err(_) => db_backup.lock().unwrap().take().unwrap(), + }; info!("Gathering inclusion proofs ..."); @@ -129,15 +159,16 @@ where info!("Saving provider cache ..."); // Save the provider cache - provider_db.get_provider().save()?; + provider_db.save_provider()?; info!("Provider-backed execution is Done!"); + // Fetch the target block Ok(Data { db: provider_db.get_initial_db().clone(), parent_header, parent_proofs, - header: block.try_into().context("invalid block")?, + header: None, transactions, withdrawals, proofs, @@ -149,7 +180,7 @@ where fn new_preflight_input( block: EthersBlock, parent_header: Header, -) -> Result> +) -> Result> where E: TxEssence + TryFrom, >::Error: Debug, @@ -176,29 +207,31 @@ where }) .collect::, _>>()?; - let input = Input { - beneficiary: from_ethers_h160(block.author.context("author missing")?), - gas_limit: from_ethers_u256(block.gas_limit), - timestamp: from_ethers_u256(block.timestamp), - extra_data: block.extra_data.0.into(), - mix_hash: from_ethers_h256(block.mix_hash.context("mix_hash missing")?), - transactions, - withdrawals, + let input = BlockBuildInput { + 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), + extra_data: block.extra_data.0.into(), + mix_hash: from_ethers_h256(block.mix_hash.context("mix_hash missing")?), + transactions, + withdrawals, + }, parent_state_trie: Default::default(), parent_storage: Default::default(), contracts: Default::default(), - parent_header, ancestor_headers: Default::default(), }; Ok(input) } -/// Converts the [Data] returned by the [Preflight] into [Input] required by the -/// [BlockBuilder]. -impl TryFrom> for Input { +/// Converts the [Data] returned by the [Preflight] into +/// [BlockBuildInput] required by the [BlockBuilder]. +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() { @@ -215,25 +248,28 @@ impl TryFrom> for Input { data.proofs, )?; - info!( + debug!( "The partial state trie consists of {} nodes", state_trie.size() ); - info!( + debug!( "The partial storage tries consist of {} nodes", storage.values().map(|(n, _)| n.size()).sum::() ); // Create the block builder input - let input = Input { - parent_header: data.parent_header, - beneficiary: data.header.beneficiary, - gas_limit: data.header.gas_limit, - timestamp: data.header.timestamp, - extra_data: data.header.extra_data.0.clone().into(), - mix_hash: data.header.mix_hash, - transactions: data.transactions, - withdrawals: data.withdrawals, + let header = data.header.as_ref().expect("Missing header data"); + let input = BlockBuildInput { + state_input: StateInput { + parent_header: data.parent_header, + beneficiary: header.beneficiary, + gas_limit: header.gas_limit, + timestamp: header.timestamp, + extra_data: header.extra_data.0.clone().into(), + mix_hash: header.mix_hash, + transactions: data.transactions, + withdrawals: data.withdrawals, + }, parent_state_trie: state_trie, parent_storage: storage, contracts: contracts.into_iter().collect(), @@ -250,7 +286,7 @@ fn proofs_to_tries( ) -> Result<(MptNode, HashMap)> { // if no addresses are provided, return the trie only consisting of the state root if parent_proofs.is_empty() { - return Ok((node_from_digest(state_root), HashMap::new())); + return Ok((state_root.into(), HashMap::new())); } let mut storage: HashMap = HashMap::with_capacity(parent_proofs.len()); @@ -281,8 +317,7 @@ fn proofs_to_tries( // if no slots are provided, return the trie only consisting of the storage root let storage_root = from_ethers_h256(proof.storage_hash); if proof.storage_proof.is_empty() { - let storage_root_node = node_from_digest(storage_root); - storage.insert(address, (storage_root_node, vec![])); + storage.insert(address, (storage_root.into(), vec![])); continue; } @@ -344,11 +379,3 @@ fn add_orphaned_leafs( Ok(()) } - -/// Creates a new MPT node from a digest. -fn node_from_digest(digest: B256) -> MptNode { - match digest { - EMPTY_ROOT | B256::ZERO => MptNode::default(), - _ => MptNodeData::Digest(digest).into(), - } -} diff --git a/lib/src/host/provider/file_provider.rs b/lib/src/host/provider/file_provider.rs index 285bd2db..ada7735b 100644 --- a/lib/src/host/provider/file_provider.rs +++ b/lib/src/host/provider/file_provider.rs @@ -19,7 +19,7 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::{anyhow, Result}; +use anyhow::{anyhow, Context, Result}; use ethers_core::types::{ Block, Bytes, EIP1186ProofResponse, Transaction, TransactionReceipt, H256, U256, }; @@ -29,7 +29,7 @@ use serde_with::serde_as; use super::{AccountQuery, BlockQuery, MutProvider, ProofQuery, Provider, StorageQuery}; #[serde_as] -#[derive(Deserialize, Serialize)] +#[derive(Clone, Deserialize, Serialize)] pub struct FileProvider { #[serde(skip)] file_path: PathBuf, @@ -85,7 +85,8 @@ impl FileProvider { pub fn save_to_file(&self, file_path: &Path) -> Result<()> { if self.dirty { let mut encoder = flate2::write::GzEncoder::new( - File::create(file_path)?, + File::create(file_path) + .with_context(|| format!("Failed to create '{}'", file_path.display()))?, flate2::Compression::best(), ); encoder.write_all(&serde_json::to_vec(self)?)?; diff --git a/lib/src/host/provider/rpc_provider.rs b/lib/src/host/provider/rpc_provider.rs index 2644e1f2..6d9bc5eb 100644 --- a/lib/src/host/provider/rpc_provider.rs +++ b/lib/src/host/provider/rpc_provider.rs @@ -17,7 +17,7 @@ use ethers_core::types::{ Block, Bytes, EIP1186ProofResponse, Transaction, TransactionReceipt, H256, U256, }; use ethers_providers::{Http, Middleware, RetryClient}; -use log::info; +use log::debug; use super::{AccountQuery, BlockQuery, ProofQuery, Provider, StorageQuery}; @@ -45,11 +45,11 @@ impl Provider for RpcProvider { } fn get_full_block(&mut self, query: &BlockQuery) -> Result> { - info!("Querying RPC for full block: {:?}", query); + debug!("Querying RPC for full block: {:?}", query); let response = self .tokio_handle - .block_on(async { self.http_client.get_block_with_txs(query.block_no).await })?; + .block_on(self.http_client.get_block_with_txs(query.block_no))?; match response { Some(out) => Ok(out), @@ -58,11 +58,11 @@ impl Provider for RpcProvider { } fn get_partial_block(&mut self, query: &BlockQuery) -> Result> { - info!("Querying RPC for partial block: {:?}", query); + debug!("Querying RPC for partial block: {:?}", query); let response = self .tokio_handle - .block_on(async { self.http_client.get_block(query.block_no).await })?; + .block_on(self.http_client.get_block(query.block_no))?; match response { Some(out) => Ok(out), @@ -71,75 +71,68 @@ impl Provider for RpcProvider { } fn get_block_receipts(&mut self, query: &BlockQuery) -> Result> { - info!("Querying RPC for block receipts: {:?}", query); + debug!("Querying RPC for block receipts: {:?}", query); let response = self .tokio_handle - .block_on(async { self.http_client.get_block_receipts(query.block_no).await })?; + .block_on(self.http_client.get_block_receipts(query.block_no))?; Ok(response) } fn get_proof(&mut self, query: &ProofQuery) -> Result { - info!("Querying RPC for inclusion proof: {:?}", query); + debug!("Querying RPC for inclusion proof: {:?}", query); - let out = self.tokio_handle.block_on(async { - self.http_client - .get_proof( - query.address, - query.indices.iter().cloned().collect(), - Some(query.block_no.into()), - ) - .await - })?; + let out = self.tokio_handle.block_on(self.http_client.get_proof( + query.address, + query.indices.iter().cloned().collect(), + Some(query.block_no.into()), + ))?; Ok(out) } fn get_transaction_count(&mut self, query: &AccountQuery) -> Result { - info!("Querying RPC for transaction count: {:?}", query); + debug!("Querying RPC for transaction count: {:?}", query); - let out = self.tokio_handle.block_on(async { + let out = self.tokio_handle.block_on( self.http_client - .get_transaction_count(query.address, Some(query.block_no.into())) - .await - })?; + .get_transaction_count(query.address, Some(query.block_no.into())), + )?; Ok(out) } fn get_balance(&mut self, query: &AccountQuery) -> Result { - info!("Querying RPC for balance: {:?}", query); + debug!("Querying RPC for balance: {:?}", query); - let out = self.tokio_handle.block_on(async { + let out = self.tokio_handle.block_on( self.http_client - .get_balance(query.address, Some(query.block_no.into())) - .await - })?; + .get_balance(query.address, Some(query.block_no.into())), + )?; Ok(out) } fn get_code(&mut self, query: &AccountQuery) -> Result { - info!("Querying RPC for code: {:?}", query); + debug!("Querying RPC for code: {:?}", query); - let out = self.tokio_handle.block_on(async { + let out = self.tokio_handle.block_on( self.http_client - .get_code(query.address, Some(query.block_no.into())) - .await - })?; + .get_code(query.address, Some(query.block_no.into())), + )?; Ok(out) } fn get_storage(&mut self, query: &StorageQuery) -> Result { - info!("Querying RPC for storage: {:?}", query); + debug!("Querying RPC for storage: {:?}", query); - let out = self.tokio_handle.block_on(async { - self.http_client - .get_storage_at(query.address, query.index, Some(query.block_no.into())) - .await - })?; + let out = self.tokio_handle.block_on(self.http_client.get_storage_at( + query.address, + query.index, + Some(query.block_no.into()), + ))?; Ok(out) } diff --git a/lib/src/host/provider_db.rs b/lib/src/host/provider_db.rs index 759547e8..6c487d87 100644 --- a/lib/src/host/provider_db.rs +++ b/lib/src/host/provider_db.rs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +extern crate alloc; + use std::collections::BTreeSet; use ethers_core::types::{EIP1186ProofResponse, H160, H256}; @@ -48,8 +50,8 @@ impl ProviderDb { } } - pub fn get_provider(&self) -> &dyn Provider { - self.provider.as_ref() + pub fn save_provider(&self) -> anyhow::Result<()> { + self.provider.save() } pub fn get_initial_db(&self) -> &MemDb { diff --git a/lib/src/host/verify.rs b/lib/src/host/verify.rs index 0afac794..e580cc8c 100644 --- a/lib/src/host/verify.rs +++ b/lib/src/host/verify.rs @@ -89,7 +89,7 @@ impl Verifier for preflight::Data { ); } - verify_header(header, &self.header) + verify_header(header, self.header.as_ref().unwrap()) } } diff --git a/lib/src/input.rs b/lib/src/input.rs index 7984e85b..a3b0ab22 100644 --- a/lib/src/input.rs +++ b/lib/src/input.rs @@ -12,10 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. +use alloy_rlp_derive::RlpEncodable; +use ethers_core::k256::sha2::{Digest, Sha256}; use hashbrown::HashMap; use serde::{Deserialize, Serialize}; use zeth_primitives::{ block::Header, + mmr::Hash, transactions::{Transaction, TxEssence}, trie::MptNode, withdrawal::Withdrawal, @@ -28,8 +31,22 @@ use zeth_primitives::{ pub type StorageEntry = (MptNode, Vec); /// External block input. -#[derive(Debug, Clone, Default, Deserialize, Serialize)] -pub struct Input { +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize)] +pub struct BlockBuildInput { + /// Block and transaction data to execute + 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. + pub parent_storage: HashMap, + /// The code of all unique contracts. + pub contracts: Vec, + /// List of at most 256 previous block headers + pub ancestor_headers: Vec
, +} + +#[derive(Debug, Clone, Default, Eq, PartialEq, Deserialize, Serialize, RlpEncodable)] +pub struct StateInput { /// Previous block header pub parent_header: Header, /// Address to which all priority fees in this block are transferred. @@ -46,14 +63,14 @@ pub struct Input { pub transactions: Vec>, /// List of stake withdrawals for execution pub withdrawals: Vec, - /// State trie of the parent block. - pub parent_state_trie: MptNode, - /// Maps each address with its storage trie and the used storage slots. - pub parent_storage: HashMap, - /// The code of all unique contracts. - pub contracts: Vec, - /// List of at most 256 previous block headers - pub ancestor_headers: Vec
, +} + +impl StateInput { + pub fn hash(&self) -> Hash { + let mut hasher = Sha256::new(); + hasher.update(&alloy_rlp::encode(self)); + hasher.finalize().into() + } } #[cfg(test)] @@ -64,21 +81,23 @@ mod tests { #[test] fn input_serde_roundtrip() { - let input = Input:: { - 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![], + 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 _: Input = + let _: BlockBuildInput = bincode::deserialize(&bincode::serialize(&input).unwrap()).unwrap(); } } diff --git a/lib/src/lib.rs b/lib/src/lib.rs index 633ebec8..96c57268 100644 --- a/lib/src/lib.rs +++ b/lib/src/lib.rs @@ -22,6 +22,7 @@ pub mod consts; pub mod input; pub mod mem_db; pub mod optimism; +pub mod output; mod utils; diff --git a/lib/src/optimism/batcher.rs b/lib/src/optimism/batcher.rs index a882b08a..96da4fa6 100644 --- a/lib/src/optimism/batcher.rs +++ b/lib/src/optimism/batcher.rs @@ -204,7 +204,7 @@ impl Batcher { while let Some(batches) = self.batcher_channel.read_batches() { batches.into_iter().for_each(|batch| { #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::trace!( "received batch: timestamp={}, parent_hash={}, epoch={}", batch.essence.timestamp, batch.essence.parent_hash, @@ -316,7 +316,7 @@ impl Batcher { match batch.essence.timestamp.cmp(&next_timestamp) { Ordering::Greater => { #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::trace!( "Future batch: {} = batch.timestamp > next_timestamp = {}", &batch.essence.timestamp, &next_timestamp @@ -325,7 +325,7 @@ impl Batcher { } Ordering::Less => { #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::trace!( "Batch too old: {} = batch.timestamp < next_timestamp = {}", &batch.essence.timestamp, &next_timestamp @@ -339,7 +339,7 @@ impl Batcher { // "batch.parent_hash != safe_l2_head.hash -> drop" if batch.essence.parent_hash != safe_l2_head.hash { #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::warn!( "Incorrect parent hash: {} != {}", batch.essence.parent_hash, safe_l2_head.hash @@ -351,7 +351,7 @@ impl Batcher { // "batch.epoch_num + sequence_window_size < inclusion_block_number -> drop" if batch.essence.epoch_num + self.config.seq_window_size < batch.inclusion_block_number { #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::warn!( "Batch is not timely: {} + {} < {}", batch.essence.epoch_num, self.config.seq_window_size, @@ -364,7 +364,7 @@ impl Batcher { // "batch.epoch_num < epoch.number -> drop" if batch.essence.epoch_num < epoch.number { #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::warn!( "Batch epoch number is too low: {} < {}", batch.essence.epoch_num, epoch.number @@ -389,7 +389,7 @@ impl Batcher { // From the spec: // "batch.epoch_num > epoch.number+1 -> drop" #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::warn!( "Batch epoch number is too large: {} > {}", batch.essence.epoch_num, epoch.number + 1 @@ -401,7 +401,7 @@ impl Batcher { // "batch.epoch_hash != batch_origin.hash -> drop" if batch.essence.epoch_hash != batch_origin.hash { #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::warn!( "Epoch hash mismatch: {} != {}", batch.essence.epoch_hash, batch_origin.hash @@ -413,7 +413,7 @@ impl Batcher { // "batch.timestamp < batch_origin.time -> drop" if batch.essence.timestamp < batch_origin.timestamp { #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::warn!( "Batch violates timestamp rule: {} < {}", batch.essence.timestamp, batch_origin.timestamp @@ -437,7 +437,7 @@ impl Batcher { // "len(batch.transactions) > 0: -> drop" if !batch.essence.transactions.is_empty() { #[cfg(not(target_os = "zkvm"))] - log::debug!("Sequencer drift detected for non-empty batch; drop."); + log::warn!("Sequencer drift detected for non-empty batch; drop."); return BatchStatus::Drop; } @@ -451,7 +451,7 @@ impl Batcher { // "If batch.timestamp >= next_epoch.time -> drop" if batch.essence.timestamp >= next_epoch.timestamp { #[cfg(not(target_os = "zkvm"))] - log::debug!("Sequencer drift detected; drop; batch timestamp is too far into the future. {} >= {}", batch.essence.timestamp, next_epoch.timestamp); + log::warn!("Sequencer drift detected; drop; batch timestamp is too far into the future. {} >= {}", batch.essence.timestamp, next_epoch.timestamp); return BatchStatus::Drop; } } else { @@ -472,7 +472,7 @@ impl Batcher { for tx in &batch.essence.transactions { if matches!(tx.first(), None | Some(&OPTIMISM_DEPOSITED_TX_TYPE)) { #[cfg(not(target_os = "zkvm"))] - log::debug!("Batch contains empty or invalid transaction"); + log::warn!("Batch contains empty or invalid transaction"); return BatchStatus::Drop; } } diff --git a/lib/src/optimism/batcher_channel.rs b/lib/src/optimism/batcher_channel.rs index c7b09b5d..3054ffdf 100644 --- a/lib/src/optimism/batcher_channel.rs +++ b/lib/src/optimism/batcher_channel.rs @@ -21,8 +21,8 @@ use anyhow::{bail, ensure, Context, Result}; use bytes::Buf; use libflate::zlib::Decoder; use zeth_primitives::{ + alloy_rlp::Decodable, batch::Batch, - rlp::Decodable, transactions::{ethereum::EthereumTxEssence, Transaction, TxEssence}, Address, BlockNumber, }; @@ -74,7 +74,7 @@ impl BatcherChannels { } #[cfg(not(target_os = "zkvm"))] - log::debug!("received batcher tx: {}", tx.hash()); + log::trace!("received batcher tx: {}", tx.hash()); // From the spec: // "If any one frame fails to parse, the all frames in the transaction are rejected." @@ -93,7 +93,7 @@ impl BatcherChannels { // load received frames into the channel bank for frame in frames { #[cfg(not(target_os = "zkvm"))] - log::debug!( + log::trace!( "received frame: channel_id={}, frame_number={}, is_last={}", frame.channel_id, frame.number, @@ -117,7 +117,7 @@ impl BatcherChannels { while matches!(self.channels.front(), Some(channel) if channel.is_ready()) { let channel = self.channels.pop_front().unwrap(); #[cfg(not(target_os = "zkvm"))] - log::debug!("received channel: {}", channel.id); + log::trace!("received channel: {}", channel.id); self.batches.push_back(channel.read_batches(block_number)); } diff --git a/lib/src/optimism/batcher_db.rs b/lib/src/optimism/batcher_db.rs index d88b2297..69a61e9d 100644 --- a/lib/src/optimism/batcher_db.rs +++ b/lib/src/optimism/batcher_db.rs @@ -17,13 +17,13 @@ use std::collections::HashMap; use anyhow::{ensure, Context, Result}; use serde::{Deserialize, Serialize}; use zeth_primitives::{ + alloy_rlp, block::Header, receipt::Receipt, transactions::{ ethereum::EthereumTxEssence, optimism::OptimismTxEssence, Transaction, TxEssence, }, trie::MptNode, - RlpBytes, }; use crate::optimism::{config::OPTIMISM_CHAIN_SPEC, deposits, system_config}; @@ -83,8 +83,7 @@ impl BatcherDb for MemDb { { let mut tx_trie = MptNode::default(); for (tx_no, tx) in op_block.transactions.iter().enumerate() { - let trie_key = tx_no.to_rlp(); - tx_trie.insert_rlp(&trie_key, tx)?; + tx_trie.insert_rlp(&alloy_rlp::encode(tx_no), tx)?; } ensure!( tx_trie.hash() == op_block.block_header.transactions_root, @@ -113,8 +112,7 @@ impl BatcherDb for MemDb { { let mut tx_trie = MptNode::default(); for (tx_no, tx) in eth_block.transactions.iter().enumerate() { - let trie_key = tx_no.to_rlp(); - tx_trie.insert_rlp(&trie_key, tx)?; + tx_trie.insert_rlp(&alloy_rlp::encode(tx_no), tx)?; } ensure!( tx_trie.hash() == eth_block.block_header.transactions_root, @@ -126,8 +124,7 @@ impl BatcherDb for MemDb { if eth_block.receipts.is_some() { let mut receipt_trie = MptNode::default(); for (tx_no, receipt) in eth_block.receipts.as_ref().unwrap().iter().enumerate() { - let trie_key = tx_no.to_rlp(); - receipt_trie.insert_rlp(&trie_key, receipt)?; + receipt_trie.insert_rlp(&alloy_rlp::encode(tx_no), receipt)?; } ensure!( receipt_trie.hash() == eth_block.block_header.receipts_root, diff --git a/lib/src/optimism/composition.rs b/lib/src/optimism/composition.rs index 7d3ad350..791c9e8c 100644 --- a/lib/src/optimism/composition.rs +++ b/lib/src/optimism/composition.rs @@ -25,10 +25,11 @@ use zeth_primitives::{ use crate::optimism::{batcher::BlockId, DeriveOutput}; /// Denotes a zkVM Image ID. -type ImageId = [u32; 8]; +pub type ImageId = [u32; 8]; #[derive(Debug, Clone, Deserialize, Serialize)] pub struct ComposeInput { + pub block_image_id: ImageId, pub derive_image_id: ImageId, pub compose_image_id: ImageId, pub operation: ComposeInputOperation, @@ -57,6 +58,7 @@ pub enum ComposeInputOperation { #[derive(Debug, Clone, Deserialize, Serialize, Eq, PartialEq)] pub struct ComposeOutput { + pub block_image_id: ImageId, pub derive_image_id: ImageId, pub compose_image_id: ImageId, pub operation: ComposeOutputOperation, @@ -95,6 +97,7 @@ impl ComposeInput { .expect("Failed to validate prior aggregation"); } // Validate context + assert_eq!(self.block_image_id, prior_output.block_image_id); assert_eq!(self.derive_image_id, prior_output.derive_image_id); assert_eq!(self.compose_image_id, prior_output.compose_image_id); assert_eq!( @@ -139,6 +142,7 @@ impl ComposeInput { } ComposeOutput { + block_image_id: self.block_image_id, derive_image_id: self.derive_image_id, compose_image_id: self.compose_image_id, operation: ComposeOutputOperation::PREP, @@ -158,6 +162,8 @@ impl ComposeInput { env::verify(Digest::from(self.derive_image_id), &derive_journal) .expect("Failed to lift derivation receipt"); } + // Verify usage of same block builder image id + assert_eq!(self.block_image_id, derive_output.block_image_id); // Verify inclusion of ethereum tail in Merkle root assert!( eth_tail_proof @@ -166,6 +172,7 @@ impl ComposeInput { ); // Create output ComposeOutput { + block_image_id: self.block_image_id, derive_image_id: self.derive_image_id, compose_image_id: self.compose_image_id, operation: ComposeOutputOperation::AGGREGATE { @@ -197,6 +204,9 @@ impl ComposeInput { .expect("Failed to verify right composition receipt"); } // Validate context + // block_image_id equality + assert_eq!(self.block_image_id, left_compose_output.block_image_id); + assert_eq!(self.block_image_id, right_compose_output.block_image_id); // derive_image_id equality assert_eq!(self.derive_image_id, left_compose_output.derive_image_id); assert_eq!(self.derive_image_id, right_compose_output.derive_image_id); @@ -233,6 +243,7 @@ impl ComposeInput { assert_eq!(&left_op_tail, &right_op_head); ComposeOutput { + block_image_id: self.block_image_id, derive_image_id: self.derive_image_id, compose_image_id: self.compose_image_id, operation: ComposeOutputOperation::AGGREGATE { @@ -266,6 +277,9 @@ impl ComposeInput { .expect("Failed to validate aggregate receipt"); } // Validate context + // block_image_id equality + assert_eq!(self.block_image_id, prep.block_image_id); + assert_eq!(self.block_image_id, aggregate.block_image_id); // derive_image_id equality assert_eq!(self.derive_image_id, prep.derive_image_id); assert_eq!(self.derive_image_id, aggregate.derive_image_id); @@ -287,6 +301,7 @@ impl ComposeInput { }; // Output new aggregate with validated chain root ComposeOutput { + block_image_id: self.block_image_id, derive_image_id: self.derive_image_id, compose_image_id: self.compose_image_id, operation: ComposeOutputOperation::AGGREGATE { diff --git a/lib/src/optimism/mod.rs b/lib/src/optimism/mod.rs index ae2e636e..381cfd20 100644 --- a/lib/src/optimism/mod.rs +++ b/lib/src/optimism/mod.rs @@ -16,11 +16,13 @@ use core::iter::once; use alloy_sol_types::{sol, SolInterface}; use anyhow::{bail, ensure, Context, Result}; -#[cfg(not(target_os = "zkvm"))] -use log::info; +#[cfg(target_os = "zkvm")] +use risc0_zkvm::{guest::env, serde::to_vec, sha::Digest}; use serde::{Deserialize, Serialize}; use zeth_primitives::{ + alloy_rlp, batch::Batch, + block::Header, keccak::keccak, transactions::{ ethereum::TransactionKind, @@ -28,16 +30,25 @@ use zeth_primitives::{ Transaction, TxEssence, }, trie::MptNode, - uint, Address, BlockHash, FixedBytes, RlpBytes, B256, U256, + uint, Address, FixedBytes, RlpBytes, B256, U256, }; +#[cfg(not(target_os = "zkvm"))] +use crate::{ + builder::{BlockBuilderStrategy, OptimismStrategy}, + consts::OP_MAINNET_CHAIN_SPEC, + host::{preflight::Preflight, provider_db::ProviderDb, ProviderFactory}, +}; use crate::{ consts::ONE, + input::{BlockBuildInput, StateInput}, optimism::{ batcher::{Batcher, BlockId, L2BlockInfo}, batcher_db::BatcherDb, + composition::ImageId, config::ChainConfig, }, + output::BlockBuildOutput, }; pub mod batcher; @@ -79,6 +90,10 @@ pub struct DeriveInput { pub op_head_block_no: u64, /// Block count for the operation. pub op_derive_block_count: u64, + /// Block building data for execution + pub op_block_outputs: Vec, + /// Image id of block builder guest + pub block_image_id: ImageId, } /// Represents the output of the derivation process. @@ -90,33 +105,45 @@ pub struct DeriveOutput { pub op_head: BlockId, /// Derived Optimism blocks. pub derived_op_blocks: Vec, + /// Image id of block builder guest + pub block_image_id: ImageId, } +#[cfg(target_os = "zkvm")] +type ProviderFactory = (); + /// Implementation of the actual derivation process. pub struct DeriveMachine { /// Input for the derivation process. pub derive_input: DeriveInput, - op_head_block_hash: BlockHash, - op_block_no: u64, + op_head_block_header: Header, op_block_seq_no: u64, pub op_batcher: Batcher, + pub provider_factory: Option, } impl DeriveMachine { /// Creates a new instance of DeriveMachine. - pub fn new(chain_config: &ChainConfig, mut derive_input: DeriveInput) -> Result { + pub fn new( + chain_config: &ChainConfig, + mut derive_input: DeriveInput, + provider_factory: Option, + ) -> Result { derive_input.db.validate()?; - - let op_block_no = derive_input.op_head_block_no; + #[cfg(not(target_os = "zkvm"))] + ensure!(provider_factory.is_some(), "Missing provider factory!"); // read system config from op_head (seq_no/epoch_no..etc) - let op_head = derive_input.db.get_full_op_block(op_block_no)?; + 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(); #[cfg(not(target_os = "zkvm"))] - info!( + log::debug!( "Fetched Op head (block no {}) {}", - op_block_no, op_head_block_hash + derive_input.op_head_block_no, + op_head_block_hash ); // the first transaction in a block MUST be a L1 attributes deposited transaction @@ -150,9 +177,10 @@ impl DeriveMachine { "Ethereum head block hash mismatch" ); #[cfg(not(target_os = "zkvm"))] - info!( + log::debug!( "Fetched Eth head (block no {}) {}", - eth_block_no, set_l1_block_values.hash + eth_block_no, + set_l1_block_values.hash ); let op_batcher = { @@ -179,25 +207,46 @@ impl DeriveMachine { Ok(DeriveMachine { derive_input, - op_head_block_hash, - op_block_no, + op_head_block_header: op_head.block_header, op_block_seq_no, op_batcher, + provider_factory, }) } - pub fn derive(&mut self) -> Result { + pub fn derive( + &mut self, + mut op_block_inputs: Option<&mut Vec>>, + ) -> Result { + #[cfg(target_os = "zkvm")] + op_block_inputs.take(); + + ensure!( + self.op_head_block_header.number == self.derive_input.op_head_block_no, + "Op head block number mismatch!" + ); let target_block_no = self.derive_input.op_head_block_no + self.derive_input.op_derive_block_count; + // Save starting op_head + let op_head = BlockId { + number: self.op_head_block_header.number, + hash: self.op_head_block_header.hash(), + }; + let mut derived_op_blocks = Vec::new(); let mut process_next_eth_block = false; - while self.op_block_no < target_block_no { + #[cfg(target_os = "zkvm")] + let mut op_block_output_iter = + core::mem::take(&mut self.derive_input.op_block_outputs).into_iter(); + + while self.op_head_block_header.number < target_block_no { #[cfg(not(target_os = "zkvm"))] - info!( + log::trace!( "op_block_no = {}, eth_block_no = {}", - self.op_block_no, self.op_batcher.state.current_l1_block_number + self.op_head_block_header.number, + self.op_batcher.state.current_l1_block_number ); // Process next Eth block. We do this on every iteration, except the first iteration. @@ -218,12 +267,11 @@ impl DeriveMachine { // Process batches while let Some(op_batch) = self.op_batcher.read_batch()? { // Process the batch - self.op_block_no += 1; #[cfg(not(target_os = "zkvm"))] - info!( + log::debug!( "Read batch for Op block {}: timestamp={}, epoch={}, tx count={}, parent hash={:?}", - self.op_block_no, + self.op_head_block_header.number + 1, op_batch.0.timestamp, op_batch.0.epoch_num, op_batch.0.transactions.len(), @@ -236,122 +284,174 @@ impl DeriveMachine { self.op_block_seq_no = 0; self.op_batcher.state.do_next_epoch()?; - self.op_batcher - .state - .epoch - .deposits - .iter() - .map(|tx| tx.to_rlp()) - .collect() + self.op_batcher.state.epoch.deposits.clone() } else { self.op_block_seq_no += 1; - Vec::new() + vec![] }; - // obtain verified op block header - let new_op_head = { - // load the next op block header - let new_op_head = self - .derive_input - .db - .get_op_block_header(self.op_block_no) - .context("op block not found")?; - - // Verify that the op block header loaded from the DB matches the payload - // attributes of the batch. - ensure!( - new_op_head.parent_hash == self.op_batcher.state.safe_head.hash, - "Invalid op block parent hash" - ); - ensure!( - new_op_head.beneficiary == self.op_batcher.config.sequencer_fee_vault, - "Invalid op block beneficiary" - ); - ensure!( - new_op_head.gas_limit == self.op_batcher.config.system_config.gas_limit, - "Invalid op block gas limit" - ); - ensure!( - new_op_head.timestamp == U256::from(op_batch.0.timestamp), - "Invalid op block timestamp" - ); - ensure!( - new_op_head.extra_data.is_empty(), - "Invalid op block extra data" - ); - - // verify that the new op head mix hash matches the mix hash of the L1 block - { - let l1_epoch_header = self - .derive_input - .db - .get_full_eth_block(op_batch.0.epoch_num) - .context("eth block not found")? - .block_header - .clone(); - ensure!( - new_op_head.mix_hash == l1_epoch_header.mix_hash, - "Invalid op block mix hash" - ); - } - - // verify that the new op head transactions match the batch transactions - { - // From the spec: - // The first transaction MUST be a L1 attributes deposited transaction, - // followed by an array of zero-or-more user-deposited transactions. - let l1_attributes_tx = self.derive_l1_attributes_deposited_tx(&op_batch); - let derived_transactions = once(l1_attributes_tx.to_rlp()) - .chain(deposits) - .chain(op_batch.0.transactions.iter().map(|tx| tx.to_vec())) - .enumerate(); - - let mut tx_trie = MptNode::default(); - for (tx_no, tx) in derived_transactions { - let trie_key = tx_no.to_rlp(); - tx_trie.insert(&trie_key, tx)?; + let l1_epoch_header_mix_hash = self + .derive_input + .db + .get_full_eth_block(op_batch.0.epoch_num) + .context("eth block not found")? + .block_header + .mix_hash; + + // From the spec: + // The first transaction MUST be a L1 attributes deposited transaction, + // followed by an array of zero-or-more user-deposited transactions. + let l1_attributes_tx = self.derive_l1_attributes_deposited_tx(&op_batch); + // TODO: revise that skipping undecodable transactions is part of spec + let decoded_batch_transactions: Vec<_> = op_batch + .0 + .transactions + .iter() + .filter_map(|raw_tx| { + match Transaction::::decode_bytes(raw_tx) { + Ok(tx) => Some(tx), + Err(_err) => { + #[cfg(not(target_os = "zkvm"))] + log::warn!("Skipping undecodable transaction: {:#}", _err); + None + } } + }) + .collect(); + + let derived_transactions: Vec<_> = once(l1_attributes_tx) + .chain(deposits) + .chain(decoded_batch_transactions) + .collect(); + let derived_transactions_rlp = derived_transactions + .iter() + .map(alloy_rlp::encode) + .enumerate(); + + let mut tx_trie = MptNode::default(); + for (tx_no, tx) in derived_transactions_rlp { + tx_trie.insert(&alloy_rlp::encode(tx_no), tx)?; + } - ensure!( - tx_trie.hash() == new_op_head.transactions_root, - "Invalid op block transactions" - ); - } + let new_op_head_input = BlockBuildInput { + state_input: StateInput { + 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(), + mix_hash: l1_epoch_header_mix_hash, + transactions: derived_transactions, + withdrawals: vec![], + }, + // initializing these fields is not needed here + parent_state_trie: Default::default(), + parent_storage: Default::default(), + contracts: vec![], + ancestor_headers: vec![], + }; - ensure!( - new_op_head.withdrawals_root.is_none(), - "Invalid op block withdrawals" + // host: go run the preflight and queue up the input data (using RLP decoded + // transactions) + #[cfg(not(target_os = "zkvm"))] + let op_block_output = { + // Create the provider DB + // todo: run without factory (using outputs) + let provider_db = ProviderDb::new( + self.provider_factory + .as_ref() + .unwrap() + .create_provider(self.op_head_block_header.number)?, + self.op_head_block_header.number, ); + let preflight_data = OptimismStrategy::preflight_with_local_data( + OP_MAINNET_CHAIN_SPEC.clone(), + provider_db, + new_op_head_input.clone(), + ) + .map(|mut headerless_preflight_data| { + let header = Header { + beneficiary: new_op_head_input.state_input.beneficiary, + gas_limit: new_op_head_input.state_input.gas_limit, + timestamp: new_op_head_input.state_input.timestamp, + extra_data: new_op_head_input.state_input.extra_data.clone(), + mix_hash: new_op_head_input.state_input.mix_hash, + // unnecessary + ..Default::default() + }; + headerless_preflight_data.header = Some(header); + headerless_preflight_data + })?; + + let executable_input: BlockBuildInput = + preflight_data.try_into()?; + if let Some(ref mut inputs_vec) = op_block_inputs { + inputs_vec.push(executable_input.clone()); + } - new_op_head + OptimismStrategy::build_from(&OP_MAINNET_CHAIN_SPEC, executable_input)? + .with_state_hashed() + }; + // guest: ask for receipt about provided block build output (compressed state trie + // expected) + #[cfg(target_os = "zkvm")] + let op_block_output = { + let output = op_block_output_iter.next().unwrap(); + // A valid receipt should be provided for block building results + let builder_journal = + to_vec(&output).expect("Failed to encode builder journal"); + env::verify( + Digest::from(self.derive_input.block_image_id), + &builder_journal, + ) + .expect("Failed to validate block build output"); + output }; - let new_op_head_hash = new_op_head.hash(); - - #[cfg(not(target_os = "zkvm"))] - info!( - "Derived Op block {} w/ hash {}", - new_op_head.number, new_op_head_hash + // Ensure that the output came from the expected input + ensure!( + new_op_head_input.state_input.hash() == op_block_output.state_input_hash(), + "Invalid state input hash" ); + match op_block_output { + BlockBuildOutput::SUCCESS { + hash: new_block_hash, + head: new_block_head, + .. + } => { + // obtain verified op block header + #[cfg(not(target_os = "zkvm"))] + log::info!( + "Derived Op block {} w/ hash {}", + new_block_head.number, + new_block_hash + ); - self.op_batcher.state.safe_head = L2BlockInfo { - hash: new_op_head_hash, - timestamp: new_op_head.timestamp.try_into().unwrap(), - l1_origin: BlockId { - number: self.op_batcher.state.epoch.number, - hash: self.op_batcher.state.epoch.hash, - }, + self.op_batcher.state.safe_head = L2BlockInfo { + hash: new_block_hash, + timestamp: new_block_head.timestamp.try_into().unwrap(), + l1_origin: BlockId { + number: self.op_batcher.state.epoch.number, + hash: self.op_batcher.state.epoch.hash, + }, + }; + + derived_op_blocks.push(BlockId { + number: new_block_head.number, + hash: new_block_hash, + }); + self.op_head_block_header = new_block_head; + + if self.op_head_block_header.number == target_block_no { + break; + } + } + BlockBuildOutput::FAILURE { .. } => { + #[cfg(not(target_os = "zkvm"))] + log::warn!("Failed to build block from batch"); + } }; - - derived_op_blocks.push(BlockId { - number: new_op_head.number, - hash: new_op_head_hash, - }); - - if self.op_block_no == target_block_no { - break; - } } } @@ -360,11 +460,9 @@ impl DeriveMachine { number: self.op_batcher.state.current_l1_block_number, hash: self.op_batcher.state.current_l1_block_hash, }, - op_head: BlockId { - number: self.derive_input.op_head_block_no, - hash: self.op_head_block_hash, - }, + op_head, derived_op_blocks, + block_image_id: self.derive_input.block_image_id, }) } diff --git a/lib/src/output.rs b/lib/src/output.rs new file mode 100644 index 00000000..d9cbcea8 --- /dev/null +++ b/lib/src/output.rs @@ -0,0 +1,74 @@ +// 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 serde::{Deserialize, Serialize}; +use zeth_primitives::{block::Header, trie::MptNode, B256}; + +/// Output of block execution +#[derive(Debug, Clone, Eq, PartialEq, Deserialize, Serialize)] +pub enum BlockBuildOutput { + SUCCESS { + hash: B256, + head: Header, + state: MptNode, + state_input_hash: B256, + }, + FAILURE { + state_input_hash: B256, + }, +} + +impl BlockBuildOutput { + /// Returns true iff of type [`BlockBuildOutput::SUCCESS`] + pub fn success(&self) -> bool { + match self { + BlockBuildOutput::SUCCESS { .. } => true, + BlockBuildOutput::FAILURE { .. } => false, + } + } + + pub fn state_input_hash(&self) -> &B256 { + match self { + BlockBuildOutput::SUCCESS { + state_input_hash, .. + } + | BlockBuildOutput::FAILURE { + state_input_hash, .. + } => state_input_hash, + } + } + + /// Replaces the `state` [`MptNode`] with its root hash + pub fn replace_state_with_hash(&mut self) -> Option { + if let BlockBuildOutput::SUCCESS { + head: new_block_head, + state: new_block_state, + .. + } = self + { + Some(core::mem::replace( + new_block_state, + new_block_head.state_root.into(), + )) + } else { + None + } + } + + /// Returns a new instance where `state` [`MptNode`] is replaced with its root hash + pub fn with_state_hashed(mut self) -> Self { + self.replace_state_with_hash(); + self + } +} diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 56cf8fbc..534315d2 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] -alloy-primitives = { version = "0.6.0", default-features = false, features = [ +alloy-primitives = { version = "0.6.2", default-features = false, features = [ "rlp", "serde", "std", @@ -14,17 +14,20 @@ 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", features = [ +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} +sha2 = { version = "=0.10.6", default-features = false } sha3 = "0.10" thiserror = "1.0" +[target.'cfg(not(target_os = "zkvm"))'.dependencies] +log = "0.4" + [dev-dependencies] bincode = "1.3" hex-literal = "0.4" diff --git a/primitives/src/access_list.rs b/primitives/src/access_list.rs index 906ce34b..03817bc8 100644 --- a/primitives/src/access_list.rs +++ b/primitives/src/access_list.rs @@ -13,7 +13,7 @@ // limitations under the License. use alloy_primitives::{Address, StorageKey}; -use alloy_rlp_derive::{RlpEncodable, RlpEncodableWrapper}; +use alloy_rlp_derive::{RlpDecodable, RlpDecodableWrapper, RlpEncodable, RlpEncodableWrapper}; use serde::{Deserialize, Serialize}; /// Represents an access list as defined in EIP-2930. @@ -21,7 +21,17 @@ use serde::{Deserialize, Serialize}; /// 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)] +#[derive( + Debug, + Clone, + PartialEq, + Eq, + Default, + Serialize, + Deserialize, + RlpEncodableWrapper, + RlpDecodableWrapper, +)] pub struct AccessList(pub Vec); /// Represents an item in the [AccessList]. @@ -29,7 +39,9 @@ pub struct AccessList(pub Vec); /// 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)] +#[derive( + Debug, Clone, PartialEq, Eq, Default, RlpEncodable, Serialize, Deserialize, RlpDecodable, +)] pub struct AccessListItem { /// The Ethereum address that the transaction will access. pub address: Address, diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 4c460ac0..7f2d5739 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -31,23 +31,26 @@ pub mod mmr; pub mod revm; pub use alloy_primitives::*; -pub use alloy_rlp as rlp; +pub use alloy_rlp; -pub trait RlpBytes { - /// Returns the RLP-encoding. - fn to_rlp(&self) -> Vec; +pub trait RlpBytes: Sized { + /// Decodes the blob into the appropriate type. + /// The input must contain exactly one value and no trailing data. + fn decode_bytes(bytes: impl AsRef<[u8]>) -> Result; } impl RlpBytes for T where - T: rlp::Encodable, + T: alloy_rlp::Decodable, { #[inline] - fn to_rlp(&self) -> Vec { - let rlp_length = self.length(); - let mut out = Vec::with_capacity(rlp_length); - self.encode(&mut out); - debug_assert_eq!(out.len(), rlp_length); - out + fn decode_bytes(bytes: impl AsRef<[u8]>) -> Result { + let mut buf = bytes.as_ref(); + let this = T::decode(&mut buf)?; + if buf.is_empty() { + Ok(this) + } else { + Err(alloy_rlp::Error::Custom("Trailing data")) + } } } diff --git a/primitives/src/transactions/ethereum.rs b/primitives/src/transactions/ethereum.rs index b48d0dbd..76593a95 100644 --- a/primitives/src/transactions/ethereum.rs +++ b/primitives/src/transactions/ethereum.rs @@ -13,9 +13,10 @@ // limitations under the License. use alloy_primitives::{Address, Bytes, ChainId, TxNumber, B256, U256}; -use alloy_rlp::{Encodable, EMPTY_STRING_CODE}; -use alloy_rlp_derive::RlpEncodable; +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, @@ -24,7 +25,11 @@ use k256::{ use serde::{Deserialize, Serialize}; use super::signature::TxSignature; -use crate::{access_list::AccessList, keccak::keccak, transactions::TxEssence}; +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). /// @@ -53,6 +58,45 @@ pub struct TxEssenceLegacy { 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. /// @@ -151,7 +195,9 @@ impl Encodable for TxEssenceLegacy { /// 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)] +#[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, @@ -175,13 +221,55 @@ pub struct TxEssenceEip2930 { 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)] +#[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. @@ -209,6 +297,48 @@ pub struct TxEssenceEip1559 { 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. /// @@ -277,6 +407,18 @@ impl Encodable for TransactionKind { } } +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. /// @@ -327,6 +469,30 @@ impl Encodable for EthereumTxEssence { } } +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. /// @@ -461,7 +627,10 @@ mod tests { use serde_json::json; use super::*; - use crate::transactions::EthereumTransaction; + use crate::{ + transactions::{EthereumTransaction, Transaction}, + RlpBytes, + }; #[test] fn legacy() { @@ -486,6 +655,10 @@ mod tests { .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(); @@ -525,6 +698,10 @@ mod tests { .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(); @@ -601,6 +778,10 @@ mod tests { .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(); @@ -642,6 +823,10 @@ mod tests { .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(); diff --git a/primitives/src/transactions/mod.rs b/primitives/src/transactions/mod.rs index c1aafb93..a8e579bd 100644 --- a/primitives/src/transactions/mod.rs +++ b/primitives/src/transactions/mod.rs @@ -12,8 +12,10 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::fmt::Debug; + use alloy_primitives::{Address, Bytes, TxHash}; -use alloy_rlp::Encodable; +use alloy_rlp::{Decodable, Encodable}; use serde::{Deserialize, Serialize}; use self::{ @@ -44,9 +46,16 @@ pub struct Transaction { 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: Encodable + Clone { +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. @@ -65,13 +74,11 @@ pub trait TxEssence: Encodable + Clone { /// and subsequently their Ethereum address. If the recovery is unsuccessful, an /// error is returned. fn recover_from(&self, signature: &TxSignature) -> anyhow::Result
; - /// Returns the length of the RLP-encoding payload in bytes. - /// - /// This method calculates the combined length of all the individual fields - /// of the transaction when they are RLP-encoded. - fn payload_length(&self) -> usize; /// 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]. @@ -124,7 +131,13 @@ impl Encodable for Transaction { } } -impl Transaction { +impl Decodable for Transaction { + fn decode(buf: &mut &[u8]) -> alloy_rlp::Result { + E::decode_signed(buf).map(|(essence, signature)| Self { essence, signature }) + } +} + +impl Transaction { /// Calculates the Keccak hash of the RLP-encoded transaction. /// /// This hash uniquely identifies the transaction on the Ethereum network. @@ -184,7 +197,7 @@ mod tests { use serde_json::json; use super::*; - use crate::transactions::EthereumTransaction; + use crate::{transactions::EthereumTransaction, RlpBytes}; #[test] fn rlp_length() { @@ -208,6 +221,10 @@ mod tests { }); let transaction: EthereumTransaction = serde_json::from_value(tx).unwrap(); + // verify the RLP roundtrip + let decoded = Transaction::decode_bytes(alloy_rlp::encode(&transaction)).unwrap(); + assert_eq!(transaction, decoded); + let encoded = alloy_rlp::encode(&transaction.essence); assert_eq!(encoded.len(), transaction.essence.length()); diff --git a/primitives/src/transactions/optimism.rs b/primitives/src/transactions/optimism.rs index be266b38..2db8c711 100644 --- a/primitives/src/transactions/optimism.rs +++ b/primitives/src/transactions/optimism.rs @@ -13,15 +13,15 @@ // limitations under the License. use alloy_primitives::{Address, Bytes, B256, U256}; -use alloy_rlp::Encodable; -use alloy_rlp_derive::RlpEncodable; -use bytes::BufMut; +use alloy_rlp::{Decodable, 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}, - TxEssence, + SignedDecodable, TxEssence, }; /// The EIP-2718 transaction type for an Optimism deposited transaction. @@ -29,7 +29,9 @@ 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)] +#[derive( + Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize, RlpEncodable, RlpDecodable, +)] pub struct TxEssenceOptimismDeposited { /// The source hash which uniquely identifies the origin of the deposit. pub source_hash: B256, @@ -83,6 +85,23 @@ impl Encodable for OptimismTxEssence { } } +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), + } + } +} + impl TxEssence for OptimismTxEssence { /// Returns the EIP-2718 transaction type. fn tx_type(&self) -> u8 { @@ -134,7 +153,10 @@ mod tests { use serde_json::json; use super::*; - use crate::transactions::OptimismTransaction; + use crate::{ + transactions::{OptimismTransaction, Transaction}, + RlpBytes, + }; #[test] fn ethereum() { @@ -165,6 +187,10 @@ mod tests { 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(); @@ -205,6 +231,10 @@ mod tests { signature: TxSignature::default(), }; + // 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(); diff --git a/primitives/src/transactions/signature.rs b/primitives/src/transactions/signature.rs index e19c0641..6150a8c3 100644 --- a/primitives/src/transactions/signature.rs +++ b/primitives/src/transactions/signature.rs @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -use alloy_primitives::U256; -use alloy_rlp_derive::{RlpEncodable, RlpMaxEncodedLen}; +use alloy_primitives::{ChainId, U256}; +use alloy_rlp_derive::RlpEncodable; use serde::{Deserialize, Serialize}; /// Represents a cryptographic signature associated with a transaction. @@ -21,9 +21,7 @@ use serde::{Deserialize, Serialize}; /// 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, -)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, RlpEncodable)] pub struct TxSignature { pub v: u64, pub r: U256, @@ -31,6 +29,15 @@ pub struct TxSignature { } 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/primitives/src/trie/mpt.rs b/primitives/src/trie/mpt.rs index d030e6f6..148c7245 100644 --- a/primitives/src/trie/mpt.rs +++ b/primitives/src/trie/mpt.rs @@ -28,7 +28,7 @@ use rlp::{Decodable, DecoderError, Prototype, Rlp}; use serde::{Deserialize, Serialize}; use thiserror::Error as ThisError; -use crate::{keccak::keccak, trie::EMPTY_ROOT, RlpBytes}; +use crate::{keccak::keccak, trie::EMPTY_ROOT}; /// Represents the root node of a sparse Merkle Patricia Trie. /// @@ -71,6 +71,15 @@ pub enum Error { LegacyRlp(#[from] DecoderError), } +impl From for MptNode { + fn from(digest: B256) -> Self { + match digest { + EMPTY_ROOT | B256::ZERO => MptNode::default(), + _ => MptNodeData::Digest(digest).into(), + } + } +} + /// Represents the various types of data that can be stored within a node in the sparse /// Merkle Patricia Trie (MPT). /// @@ -564,7 +573,7 @@ impl MptNode { /// This method inserts a value that's been encoded using RLP into the trie. #[inline] pub fn insert_rlp(&mut self, key: &[u8], value: impl Encodable) -> Result { - self.insert_internal(&to_nibs(key), value.to_rlp()) + self.insert_internal(&to_nibs(key), alloy_rlp::encode(value)) } fn insert_internal(&mut self, key_nibs: &[u8], value: Vec) -> Result { @@ -843,7 +852,7 @@ mod tests { let node: MptNode = MptNodeData::Leaf(k.as_bytes().to_vec(), v.as_bytes().to_vec()).into(); assert!( - matches!(node.reference(),MptNodeReference::Bytes(bytes) if bytes == node.to_rlp().to_vec()) + matches!(node.reference(),MptNodeReference::Bytes(bytes) if bytes == alloy_rlp::encode(&node)) ); } } @@ -958,7 +967,7 @@ mod tests { **node = MptNodeData::Digest(node.hash()).into(); assert!(node.is_digest()); - let trie = MptNode::decode(trie.to_rlp()).unwrap(); + let trie = MptNode::decode(alloy_rlp::encode(&trie)).unwrap(); assert_eq!(trie.hash(), exp_hash); // lookups should fail @@ -1007,7 +1016,7 @@ mod tests { assert!(!trie.insert(vals[0].0.as_bytes(), b"new".to_vec()).unwrap()); // try RLP roundtrip - let decoded = MptNode::decode(trie.to_rlp()).unwrap(); + let decoded = MptNode::decode(alloy_rlp::encode(&trie)).unwrap(); assert_eq!(trie.hash(), decoded.hash()); } @@ -1057,33 +1066,33 @@ mod tests { // insert let mut trie = MptNode::default(); for i in 0..N { - assert!(trie.insert_rlp(&i.to_rlp(), i).unwrap()); + assert!(trie.insert_rlp(&alloy_rlp::encode(i), i).unwrap()); // check hash against trie build in reverse let mut reference = MptNode::default(); for j in (0..=i).rev() { - reference.insert_rlp(&j.to_rlp(), j).unwrap(); + reference.insert_rlp(&alloy_rlp::encode(j), j).unwrap(); } assert_eq!(trie.hash(), reference.hash()); // try RLP roundtrip - let decoded = MptNode::decode(trie.to_rlp()).unwrap(); + let decoded = MptNode::decode(alloy_rlp::encode(&trie)).unwrap(); assert_eq!(trie.hash(), decoded.hash()); } // get for i in 0..N { - assert_eq!(trie.get_rlp(&i.to_rlp()).unwrap(), Some(i)); - assert!(trie.get(&(i + N).to_rlp()).unwrap().is_none()); + assert_eq!(trie.get_rlp(&alloy_rlp::encode(i)).unwrap(), Some(i)); + assert!(trie.get(&alloy_rlp::encode(i + N)).unwrap().is_none()); } // delete for i in 0..N { - assert!(trie.delete(&i.to_rlp()).unwrap()); + assert!(trie.delete(&alloy_rlp::encode(i)).unwrap()); let mut reference = MptNode::default(); for j in ((i + 1)..N).rev() { - reference.insert_rlp(&j.to_rlp(), j).unwrap(); + reference.insert_rlp(&alloy_rlp::encode(j), j).unwrap(); } assert_eq!(trie.hash(), reference.hash()); } diff --git a/testing/ef-tests/src/ethtests.rs b/testing/ef-tests/src/ethtests.rs index 6ea7f2a0..ae850480 100644 --- a/testing/ef-tests/src/ethtests.rs +++ b/testing/ef-tests/src/ethtests.rs @@ -35,7 +35,7 @@ pub fn read_eth_test(path: PathBuf) -> Vec { root.as_object_mut() .unwrap() .into_iter() - .map(|(name, test)| { + .filter_map(|(name, test)| { println!("test '{}'", name); let json: TestJson = serde_json::from_value(test.take()).unwrap(); @@ -56,6 +56,5 @@ pub fn read_eth_test(path: PathBuf) -> Vec { chain_spec, }) }) - .flatten() .collect() } diff --git a/testing/ef-tests/src/lib.rs b/testing/ef-tests/src/lib.rs index 4772b3a8..494eb557 100644 --- a/testing/ef-tests/src/lib.rs +++ b/testing/ef-tests/src/lib.rs @@ -26,11 +26,12 @@ use zeth_lib::{ provider::{AccountQuery, BlockQuery, ProofQuery, Provider, StorageQuery}, provider_db::ProviderDb, }, - input::Input, + input::{BlockBuildInput, StateInput}, mem_db::{AccountState, DbAccount, MemDb}, }; use zeth_primitives::{ access_list::{AccessList, AccessListItem}, + alloy_rlp, block::Header, ethers::from_ethers_h160, keccak::keccak, @@ -43,7 +44,7 @@ use zeth_primitives::{ }, trie::{self, MptNode, MptNodeData, StateAccount}, withdrawal::Withdrawal, - Address, Bloom, Bytes, RlpBytes, StorageKey, B256, B64, U256, U64, + Address, Bloom, Bytes, StorageKey, B256, B64, U256, U64, }; use crate::ethers::TestProvider; @@ -96,8 +97,8 @@ impl From for TestAccount { TestAccount { balance: account.info.balance, nonce: U64::from(account.info.nonce), - code: account.info.code.unwrap().bytecode.into(), - storage: account.storage.into_iter().map(|(k, v)| (k, v)).collect(), + code: account.info.code.unwrap().bytecode, + storage: account.storage.into_iter().collect(), } } } @@ -278,7 +279,7 @@ pub fn mpt_proof(root: &MptNode, key: impl AsRef<[u8]>) -> Result>, fn proof_internal(node: &MptNode, key_nibs: &[u8]) -> Result>, anyhow::Error> { if key_nibs.is_empty() { - return Ok(vec![node.to_rlp()]); + return Ok(vec![alloy_rlp::encode(node)]); } let mut path: Vec> = match node.as_data() { @@ -299,7 +300,7 @@ fn proof_internal(node: &MptNode, key_nibs: &[u8]) -> Result>, anyho } MptNodeData::Digest(_) => bail!("Cannot descend pointer!"), }; - path.push(node.to_rlp()); + path.push(alloy_rlp::encode(node)); Ok(path) } @@ -315,7 +316,7 @@ pub fn create_input( transactions: Vec, withdrawals: Vec, state: TestState, -) -> Input { +) -> BlockBuildInput { // create the provider DB let provider_db = ProviderDb::new( Box::new(TestProvider { @@ -330,24 +331,26 @@ pub fn create_input( .into_iter() .map(EthereumTransaction::from) .collect(); - let input = Input { - beneficiary: header.beneficiary, - gas_limit: header.gas_limit, - timestamp: header.timestamp, - extra_data: header.extra_data.clone(), - mix_hash: header.mix_hash, - transactions: transactions.clone(), - withdrawals: withdrawals.clone(), + let input = BlockBuildInput { + state_input: StateInput { + beneficiary: header.beneficiary, + gas_limit: header.gas_limit, + timestamp: header.timestamp, + extra_data: header.extra_data.clone(), + mix_hash: header.mix_hash, + transactions: transactions.clone(), + withdrawals: withdrawals.clone(), + parent_header: parent_header.clone(), + }, parent_state_trie: Default::default(), parent_storage: Default::default(), contracts: vec![], - parent_header: parent_header.clone(), ancestor_headers: vec![], }; // create and run the block builder once to create the initial DB - let mut builder = BlockBuilder::new(&chain_spec, input) + let mut builder = BlockBuilder::new(chain_spec, input, None) .with_db(provider_db) .prepare_header::<::HeaderPrepStrategy>() .unwrap() @@ -363,7 +366,7 @@ pub fn create_input( db: provider_db.get_initial_db().clone(), parent_header, parent_proofs, - header, + header: Some(header), transactions, withdrawals, proofs, diff --git a/testing/ef-tests/testguest/Cargo.lock b/testing/ef-tests/testguest/Cargo.lock index 2a7aef20..c1ab06ff 100644 --- a/testing/ef-tests/testguest/Cargo.lock +++ b/testing/ef-tests/testguest/Cargo.lock @@ -52,9 +52,9 @@ checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "alloy-primitives" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3729132072f369bc4e8e6e070f9cf4deb3490fc9b9eea6f71f75ec19406df811" +checksum = "f4b6fb2b432ff223d513db7f908937f63c252bee0af9b82bfd25b0a5dd1eb0d8" dependencies = [ "alloy-rlp", "bytes", @@ -95,14 +95,14 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5531f0a16e36c547e68c73a1638bea1f26237ee8ae785527190c4e4f9fecd2c5" +checksum = "8b0b5ab0cb07c21adf9d72e988b34e8200ce648c2bba8d009183bb1c50fb1216" dependencies = [ "const-hex", "dunce", "heck", - "indexmap 2.1.0", + "indexmap 2.2.1", "proc-macro-error", "proc-macro2", "quote", @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "783eb720b73d38f9d4c1fb9890e4db6bc8c708f7aa77d3071a19e06091ecd1c9" +checksum = "6c08f62ded7ce03513bfb60ef5cad4fff5d4f67eac6feb4df80426b7b9ffb06e" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -418,14 +418,13 @@ dependencies = [ [[package]] name = "auto_impl" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" +checksum = "823b8bb275161044e2ac7a25879cb3e2480cb403e3943022c7c769c599b756aa" dependencies = [ - "proc-macro-error", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.48", ] [[package]] @@ -473,6 +472,15 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + [[package]] name = "bindgen" version = "0.66.1" @@ -583,9 +591,9 @@ checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9" dependencies = [ "bytemuck_derive", ] @@ -657,9 +665,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.32" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41daef31d7a747c5c847246f36de49ced6f7403b4cdabc807a97b5cc184cda7a" +checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" dependencies = [ "android-tzdata", "iana-time-zone", @@ -777,9 +785,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +checksum = "da01daa5f6d41c91358398e8db4dde38e292378da1f28300b59ef4732b879454" dependencies = [ "darling_core", "darling_macro", @@ -787,9 +795,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +checksum = "f44f6238b948a3c6c3073cdf53bb0c2d5e024ee27e0f35bfe9d556a12395808a" dependencies = [ "fnv", "ident_case", @@ -801,9 +809,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +checksum = "0d2d88bd93979b1feb760a6b5c531ac5ba06bd63e74894c377af02faee07b9cd" dependencies = [ "darling_core", "quote", @@ -1358,7 +1366,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap 2.1.0", + "indexmap 2.2.1", "slab", "tokio", "tokio-util", @@ -1607,9 +1615,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "433de089bd45971eecf4668ee0ee8f4cec17db4f8bd8f7bc3197a6ce37aa7d9b" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -2090,18 +2098,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", @@ -2330,9 +2338,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b7fa1134405e2ec9353fd416b17f8dacd46c473d7d3fd1cf202706a14eb792a" +checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd" dependencies = [ "aho-corasick", "memchr", @@ -2880,18 +2888,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.195" +version = "1.0.196" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" dependencies = [ "proc-macro2", "quote", @@ -2900,11 +2908,11 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.111" +version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" +checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "itoa", "ryu", "serde", @@ -2924,15 +2932,15 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58c3a1b3e418f61c25b2aeb43fc6c95eaa252b8cecdda67f401943e9e08d33f" +checksum = "f5c9fdb6b00a489875b22efd4b78fe2b363b72265cc5f6eb2e2b9ee270e6140c" dependencies = [ "base64 0.21.7", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.1.0", + "indexmap 2.2.1", "serde", "serde_json", "serde_with_macros", @@ -2941,9 +2949,9 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.5.0" +version = "3.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2068b437a31fc68f25dd7edc296b078f04b45145c199d8eed9866e45f1ff274" +checksum = "dbff351eb4b33600a2e138dfa0b10b65a238ea8ff8fb2387c422c5022a3e8298" dependencies = [ "darling", "proc-macro2", @@ -3153,9 +3161,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cfbd642e1748fd9e47951973abfa78f825b11fbf68af9e6b9db4c983a770166" +checksum = "63bef2e2c735acbc06874eca3a8506f02a3c4700e6e748afc92cc2e4220e8a03" dependencies = [ "paste", "proc-macro2", @@ -3374,7 +3382,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3385,7 +3393,7 @@ version = "0.20.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3396,7 +3404,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ - "indexmap 2.1.0", + "indexmap 2.2.1", "toml_datetime", "winnow", ] @@ -3866,9 +3874,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.34" +version = "0.5.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cf47b659b318dccbd69cc4797a39ae128f533dce7902a1096044d1967b9c16" +checksum = "1931d78a9c73861da0134f453bb1f790ce49b2e30eba8410b4b79bac72b46a2d" dependencies = [ "memchr", ] @@ -3955,8 +3963,12 @@ dependencies = [ name = "zeth-lib" version = "0.1.0" dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-rlp-derive", "alloy-sol-types", "anyhow", + "bincode", "bytes", "chrono", "ethers-core", @@ -3988,6 +4000,7 @@ dependencies = [ "bytes", "ethers-core", "k256", + "log", "revm-primitives", "rlp", "serde", diff --git a/testing/ef-tests/testguest/src/main.rs b/testing/ef-tests/testguest/src/main.rs index 6abd32f6..53a05456 100644 --- a/testing/ef-tests/testguest/src/main.rs +++ b/testing/ef-tests/testguest/src/main.rs @@ -28,10 +28,15 @@ pub fn main() { // Read the input previous block and transaction data let input = env::read(); // Build the resulting block - let (header, state) = EthereumStrategy::build_from(&chain_spec, input) + let mut output = EthereumStrategy::build_from(&chain_spec, input) .expect("Failed to build the resulting block"); - // Output the resulting block's hash to the journal - env::commit(&header.hash()); + // Abridge successful construction results + if let Some(replaced_state) = output.replace_state_with_hash() { + // Leak memory, save cycles + core::mem::forget(replaced_state); + } + // Output the construction result + env::commit(&output); // Leak memory, save cycles - core::mem::forget((header, state)); + core::mem::forget(output); } diff --git a/testing/ef-tests/tests/evm.rs b/testing/ef-tests/tests/evm.rs index 4bd686bd..be59605f 100644 --- a/testing/ef-tests/tests/evm.rs +++ b/testing/ef-tests/tests/evm.rs @@ -17,7 +17,10 @@ use std::path::PathBuf; use rstest::rstest; -use zeth_lib::builder::{BlockBuilderStrategy, EthereumStrategy}; +use zeth_lib::{ + builder::{BlockBuilderStrategy, EthereumStrategy}, + output::BlockBuildOutput, +}; use zeth_primitives::{block::Header, trie::StateAccount}; use zeth_testeth::{ create_input, ethers, @@ -69,15 +72,26 @@ fn evm( block.withdrawals.unwrap_or_default(), post_state, ); + let input_state_input_hash = input.state_input.hash(); + + let output = EthereumStrategy::build_from(&chain_spec, input).unwrap(); - let (header, state) = EthereumStrategy::build_from(&chain_spec, input).unwrap(); + let BlockBuildOutput::SUCCESS { + hash: new_block_hash, + head: new_block_head, + state: new_block_state, + state_input_hash, + } = output + else { + panic!("Invalid block") + }; if let Some(post) = json.post { let (exp_state, _) = ethers::build_tries(&post); println!("diffing state trie:"); for diff in diff::slice( - &state.debug_rlp::(), + &new_block_state.debug_rlp::(), &exp_state.debug_rlp::(), ) { match diff { @@ -86,11 +100,12 @@ fn evm( diff::Result::Both(l, _) => println!(" {}", l), } } - assert_eq!(state.hash(), exp_state.hash()); + assert_eq!(new_block_state.hash(), exp_state.hash()); } // the headers should match - assert_eq!(header, expected_header); - assert_eq!(header.hash(), expected_header.hash()); + assert_eq!(new_block_head, expected_header); + assert_eq!(new_block_hash, expected_header.hash()); + 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 7321e30d..baecba67 100644 --- a/testing/ef-tests/tests/executor.rs +++ b/testing/ef-tests/tests/executor.rs @@ -19,7 +19,8 @@ use std::path::PathBuf; use risc0_zkvm::{ExecutorEnv, ExecutorImpl, FileSegmentRef}; use rstest::rstest; use tempfile::tempdir; -use zeth_primitives::{block::Header, BlockHash}; +use zeth_lib::output::BlockBuildOutput; +use zeth_primitives::block::Header; use zeth_testeth::{ create_input, ethtests::{read_eth_test, EthTestCase}, @@ -89,8 +90,15 @@ fn executor( .unwrap(); println!("Generated {} segments", session.segments.len()); - let found_hash: BlockHash = session.journal.unwrap().decode().unwrap(); - println!("Block hash (from executor): {}", found_hash); - assert_eq!(found_hash, expected_header.hash()); + let build_output: BlockBuildOutput = session.journal.unwrap().decode().unwrap(); + let BlockBuildOutput::SUCCESS { + hash: new_block_hash, + .. + } = build_output + else { + panic!("Block build failed!") + }; + println!("Block hash (from executor): {}", new_block_hash); + assert_eq!(new_block_hash, expected_header.hash()); } }