From 0dddd3cb449151b60db786953291d13b0a935a57 Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Sun, 12 May 2024 23:41:59 -0700 Subject: [PATCH 01/30] Adding --- Cargo.lock | 78 ++ Cargo.toml | 1 + testing/zkvm/Cargo.lock | 740 +++++++++++++++++++ testing/zkvm/Cargo.toml | 16 + testing/zkvm/compile.sh | 39 + testing/zkvm/elf/riscv32im-succinct-zkvm-elf | Bin 0 -> 127664 bytes testing/zkvm/src/main.rs | 22 + 7 files changed, 896 insertions(+) create mode 100644 testing/zkvm/Cargo.lock create mode 100644 testing/zkvm/Cargo.toml create mode 100644 testing/zkvm/compile.sh create mode 100755 testing/zkvm/elf/riscv32im-succinct-zkvm-elf create mode 100644 testing/zkvm/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index fc5e8abea480..7efe43533cf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2719,6 +2719,7 @@ dependencies = [ "rand_core 0.6.4", "sec1", "subtle", + "tap", "zeroize", ] @@ -3072,6 +3073,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ + "bitvec", "rand_core 0.6.4", "subtle", ] @@ -8515,6 +8517,30 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scale-info" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "scc" version = "2.1.1" @@ -9004,6 +9030,16 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" +[[package]] +name = "snowbridge-amcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460a9ed63cdf03c1b9847e8a12a5f5ba19c4efd5869e4a737e05be25d7c427e5" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + [[package]] name = "socket2" version = "0.4.10" @@ -9040,6 +9076,40 @@ dependencies = [ "sha-1", ] +[[package]] +name = "sp1-precompiles" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "getrandom 0.2.15", + "hex", + "k256", + "num", + "rand 0.8.5", + "serde", + "snowbridge-amcl", +] + +[[package]] +name = "sp1-zkvm" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +dependencies = [ + "bincode", + "cfg-if", + "getrandom 0.2.15", + "k256", + "libm", + "once_cell", + "rand 0.8.5", + "serde", + "sha2 0.10.8", + "sp1-precompiles", +] + [[package]] name = "spin" version = "0.5.2" @@ -10677,6 +10747,14 @@ dependencies = [ "syn 2.0.63", ] +[[package]] +name = "zkvm-test" +version = "0.2.0-beta.7" +dependencies = [ + "reth-primitives", + "sp1-zkvm", +] + [[package]] name = "zstd" version = "0.13.1" diff --git a/Cargo.toml b/Cargo.toml index 1429909df29c..2fb6c54b268c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -92,6 +92,7 @@ members = [ "examples/db-access", "testing/ef-tests/", "testing/testing-utils", + "testing/zkvm", ] default-members = ["bin/reth"] diff --git a/testing/zkvm/Cargo.lock b/testing/zkvm/Cargo.lock new file mode 100644 index 000000000000..d50e50e888bc --- /dev/null +++ b/testing/zkvm/Cargo.lock @@ -0,0 +1,740 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64ct" +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 = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "tap", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "minimal-reth-program" +version = "0.1.0" +dependencies = [ + "sp1-zkvm", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "scale-info" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.63", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "snowbridge-amcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460a9ed63cdf03c1b9847e8a12a5f5ba19c4efd5869e4a737e05be25d7c427e5" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "sp1-precompiles" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "getrandom", + "hex", + "k256", + "num", + "rand", + "serde", + "snowbridge-amcl", +] + +[[package]] +name = "sp1-zkvm" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +dependencies = [ + "bincode", + "cfg-if", + "getrandom", + "k256", + "libm", + "once_cell", + "rand", + "serde", + "sha2", + "sp1-precompiles", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/testing/zkvm/Cargo.toml b/testing/zkvm/Cargo.toml new file mode 100644 index 000000000000..0f0c81c49494 --- /dev/null +++ b/testing/zkvm/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "zkvm-test" +description = "Test zkvm imports" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[lints] +workspace = true + +[dependencies] +sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git" } +reth-primitives.workspace = true diff --git a/testing/zkvm/compile.sh b/testing/zkvm/compile.sh new file mode 100644 index 000000000000..703117f3a986 --- /dev/null +++ b/testing/zkvm/compile.sh @@ -0,0 +1,39 @@ +# CARGO_ENCODED_RUSTFLAGS + + +# // Construct command from the toolchain-specific cargo +# let mut cmd = +# Command::new(cargo.map_or("cargo".to_string(), |c| String::from(c.to_str().unwrap()))); +# // Clear unwanted env vars +# self.sanitize(&mut cmd, true); +# cmd.current_dir(ROOT_DIR.get().unwrap()); + +# // Set Rustc compiler path and flags +# cmd.env( +# "RUSTC", +# rustc.map_or("rustc".to_string(), |c| String::from(c.to_str().unwrap())), +# ); +# if let Some(rust_flags) = rust_flags { +# cmd.env( +# "CARGO_ENCODED_RUSTFLAGS", +# format_flags("-C", &rust_flags).join("\x1f"), +# ); +# } + +# // Set C compiler path and flags +# if let Some(cc_compiler) = cc_compiler { +# cmd.env("CC", cc_compiler); +# } +# if let Some(c_flags) = c_flags { +# cmd.env(format!("CC_{}", self.target), c_flags.join(" ")); +# } + +export PATH="$HOME/riscv/bin:$PATH" +export RUSTUP_TOOLCHAIN="succinct" +export RUSTFLAGS="-C passes=loweratomic -C link-arg=-Ttext=0x00200800 -C panic=abort" +export CARGO_BUILD_TARGET="riscv32im-succinct-zkvm-elf" +export CC="gcc" +export CC_riscv32im_succinct_zkvm_elf="$HOME/riscv/bin/riscv32-unknown-elf-gcc -mstrict-align" +cargo build --release --ignore-rust-version + +# https://github.com/taikoxyz/raiko/blob/6a8421d5c17a7d8846c22f8f986d9584a6885bf1/script/install.sh#L4 \ No newline at end of file diff --git a/testing/zkvm/elf/riscv32im-succinct-zkvm-elf b/testing/zkvm/elf/riscv32im-succinct-zkvm-elf new file mode 100755 index 0000000000000000000000000000000000000000..e9f3e1c3b9e2ca237a312ea253021be9c3c92b1f GIT binary patch literal 127664 zcmeFa349gR+4z6v&YgRc7#5iKn_YDb7&ewv6kLEBebF#)WFY9uULHw@rL{@>@!+>o%?_HEza|MU6( z%jXm3o|$u=^PJ~A`#E#wma?yoGYmte|Ao{(C8aBR7pT*@{_$P^+3Bi4Mb$8st+G^v z`||8`YRcbV`7M9p;O{Ur`DLgaF7hYORZqFYzYO^+(0_G*QcC_TxgR{Q+s3^;1^Tao z&g8Fi`;zX4Dj7LQ{|%$rZvF%>X@B9)8?KO_NB+~#xoIkOUATwFLRT5Y|MDmB58u^~ z{`22|DDWQ&{D%Vnp}>DA@c&5)*oN^*Y~+cd*oewdZ1_E)*swuntmyM*Y)GjY8+@S| zEBLl)XP%~Fg9jP0;eS%GVf89j^tg%*S*h%>GTd;bax+Vmoz+vhS*L~U6AIL|szSxX z;SAfVG+e7x*;QfXM#5?dws}`Y-E_08(ufZjWtfHaMm%g~#IIhJ?SxmAcym{&Yu{b* zN&J#WRDx%TR8qxnD>trHb)k4pnVBfN$B5ruZnjJ-{8-v13d@vPXsN_%3%C|-cN{be z>2p?F4?9w#;`gO85(V|9Ii%7|Fdp+{!%Uo9A2Nqmh7!X|L+0m<5aSQetWc`Btw6a} z@@KYHpvNX-1pfeM^&J_n)UmDP+FGewm0BTJyE?VbwMq;-Lfyw?d=-7K@2TqavnuN` z*J9jt`u>mQzKrYIcL#nXc;~xH%~Xlsn`=_g!cy++h!MXpqU_m`P`qzMk9w6ah+Mjn8#5sX{mTcB+MAvV?`$_JCXA4}Q^x^+F5xFn$Z5iK2}m z8JEN*jmouvB?a1AX>oFB8xKJ&5 zP-t5+lQ9|e6Ou6r{zuW$$K{rQhPMT{FVyv+eWDE9s@mG!$aN}yL$i|mEz7M#iLx^2 zdYWoknmS|_CgDq;=gb<5v6(_gO?yp)GRB=-sA>i8s>lP5)ua;8M&@Z|1VIMD0sH>^Ri$0&#OH8M+Q{4uJfCG!hbIFtDm0`%;g3tr{_2r=hwQzZmSLY z{xy9AyCmwjE&GifdGLs~W6t%T?fk9Ky(`?rc>md~-`SCG9no%MS=TZOmW@*GqNMV6rj)xlV%WJ!!iS?1rAG;=Iu2C zPs0^G3LNMaLZ^iiL(pL-8zFR>@V=REioA`fv8@sn8;-sz1g4ey_1G|UwPhGS{YnN% zxmfG6vgLaII&@ibjca`iT}EB4%j*7Hbe5jC$heft`0TW7>%KO23+7DAH#UTR@4-f3 zD~g!2`Os!AGznYj{!(e(;E$~?)6GPODJvAeVu)dfp;3~tCZVC&3qAh2OXVJ8HW;(P zm<`5kFlONuE${gWJ?^gwE&)DTCf#aF>v9>ZYqd4%F-NWE>_|^T^r4-MruD~}z!!L0 zCl-$ygg#5Py6A&=9=KCR@4xTOZc=t_p7N4SCBi4(tXkzHS1TuyQni-Kc9Xd(e&YsJ zOa0iIRIA|PkD+3K&=L5@q*IJB+2IJfuRvYTm_^^jd#8G8Jc`QpqC@sNtqm&PJ<`** zti9&BRutX|JCVZD_zlm7eEg_m6(T2=d6;%;f)}0-FV~$A@17ZU!q1j?^HctKvaG#s zILmaB&^`0E08dqB7Ty+06h0qu7KZHBMT9Y6a2E*Tw4`NtZfL{$tvWhQ8~rCl~cV-#a2bk*qYXm52xbeU<`jt z^SMtq^<}vq%UJa8vF0B;-oXO_Kc|GB?W(dryVhf&fQQc%+PfjuL(?`H(mdjZdg^j# zezB`Weuc*i((?u#kVEaasCjx0kyqU&xcV};@pZrd)a!nq>c2i~z7s>RmnSFb#|ZeZ zt}vdR8M6DF?8`~G>`iz6Sm=I_uH)i|=sB$ueW3nqXFk{N&dpRU12R9+F!cSp_l`xQ zw2W{)re2MWD8;Y4(1;EDwvl+mGUB&pb$5|j8<{m9DO29mOU(F|AL+r2Xkcj-LC*_~l{GY_iRgZtsRT=d{L z)$)VqKZzBr!Z$tLhz)t-n0gT&G4S;ad_AorW$ygBvfl7{CAG)3?hf>w>L>HIbI(|#vKz!T++Ed%6WL#a9V8B*&37ZFSG6C!-!-I<4!B3cd2|Ew899W{ z6KeTx<0nF6cRzM`L!PpW(U+~QD*iyEyIYM;$zaa0n>N4QNN*KWy|Fj@8B?+HMm?sS zGwPIg&@$ZWd}tZfwzXwx#wTvuXcfQJ%66kF6u)NwU>91(tJ-?GQEd9HZGGKnPZhtn zZE#{}RK+Ubk)~=@QvqIEqlTLttzwn<0+D9?yC`&1hPiHBySt^@aC^^FiHEA%yo;bx*b{RqirU3NbqmD*ZKh7H{##j5OS?|@rR?z95!AhhE=P?;6}~cv4I^<_>NYgH9>tCc%zoX{vwp35_l5s@SC$d$g_ zWS*vtrnja;L7ENrdQ1s$|}9-9t%(4itDJumiF@Jtq|nhKeZ z)?hw*26!-6$a_~jGMJCh5qN}{59)Q95786R&%mRIxnUk=5o6tJWoTM1wR&or&9g!Y z3z|mJMHxe((FX9_uM$?V&o|J}tsbXpDut%daaNIvFBMpMD!$m#K1jN~w6&u{gE7k7 z`1M*ASf5B8c`oviu79ll67*+gOxFD+teGly>wZ;pYs5%I=crg>18u8$zC_g|z%ja3 z#pZ(VT%KFCDwdRcjXd9?YLZfSmx>|7HSlF3dO*dh1wWCAh*49W#;;1X++n@_ui&Kl zFIlB=^2dyRUTp2f&;8qyL56ZG>;IBZjvqU8g-Q7xg?$KOCwzT$(LJj8^g;NF;k|Y; zj1SW@EOsLB1AZPG%zbPz`hIWm&djTAYu1d|s#U6Z{mkFmR{8GO8h*E3^JUvAERL;{ z-xsX5t<@7_kMO&^`-QgEHZ=Bge$TS*x2@E?*rWX3nHXqW>+g#_xGGfK^w&#mYtf%# z53LHt)`UZ`RpHQ*ciY>EEsO0AJnEvN(~lb;>lib!EQsq@`PYrV5F3IXc+-v)1o1Di zu`51n;vCHj#FX(nu(!ma?xI3%8}s+IxAXiwc@CZ4BPQw&ow`G(?!-hrh>5ykySrh# zyJ5S##frY)jpyBJ#dlp}?TtOe--FiPcrSc0@rkUmx3ul5Dr-CJ8>ydbyM?Vsf9-XX zzE46t5)J6S$}A+lC@c+;=LwnTRz~bevkZ6fBIWFAP;UMrW%vFfIuJdTo2zOwnCE#J z?>e(`4biRMRc*?dg?`UXQuo(}vv)1y%T-Pr&zq|Z?`q<*S^4_8omXWz-&un{Jw$ws z3_J3!DRwiS{hYGLeQ1h5+KC@-_pbVqVVBJ}U8_PlS6ynvf4Dv(zL5B+5i-XQOLdKq$-wYmi4YPdyR6NlZG>+S$X?c6Ps2kb7-l=s)o0- zNyn@9B8iXXXLr%~_}Yti&*U2lTzzH>vAxnWsE~flU)1%sIG@dBxrhF74ub zVF#6SBQUUs&Xv6l@8Cn|{&~ubk#oEER>RxfOY2{EN&*{By^9juBYyrt4R!;Y8ml*K zn|sqHDyi$fM7{SPQub!@Ts3Cs>ueb@r*;%8U>E-yqk7vY+>N8@){*)0L{#r(C z#CsXBkw#{$;KUPRgI8uTzgaRTvEh$Lm}Byok4Iu7S4Lt52Kh(g;K3`o%Dk0EeR;0C zz$~n!T%qE5>+|4mWsbn6ey&WJpG&I5@RTx#Tf~=T#FT7&R)=f`aC#C` z5O3k@SlK#m^UK12Cv++!`&Q@jX*|#B^t^=Uoy%Y6d1j~Q-{N`a@^zZOC6;kR4+j0K zpuUvpADj+9m;O7K>Ay=^`tSUl{=1Z=|IW|pzoU$9BHtl>1v+NGuVYdNp>N2~&DBj8 z9g`3`7nP#F$sG@_XI|4eh}4JD#;r}sn!^MDWaco2gqPwVm{=wJ>hV_bd?LvXTb<1+4mhhHZy3&mJ@j}2bL zoWTF&L5`vY^`);R%mMlB-a$V*ut^26A(aK#qylu|AZ*e=Y|=n%(m-s|Ky1=Lo)6^t zz*xb`fw7T~pJbkjof`>GG5Q*oQi+k4VGb)Z5<`>FVI?{dS<8v2Yft;*HFn+% zD5@tHa@#rNU_PWy&*HM;?_&?nMYekuTlMR)?Y{$l&*Giy_uvcs2Knz^oSO7SY z6!`qkE@vKI1%7t%^rwCRoGrl5E?&Q#x!)=9vx}`)@h@gw4gBolw)^X;lMnpt;#v2< z0n7)0pIuz`)H}8{{YKzt7q71G!S7dr&+lydO7#bRR`IAkr!cMt;Aa&lZ#WNM<~-nM z6|aBn8`SwJ@Uw~+eK?!@cLG1Fxcsc8_&&M7&nixRew}SK%>aH@aiRGbot(q{#lWY2?NDg74)__x zh5beX(*}M<@vISF1D_qhr_LD@f%zxkM~Y` zj}(vk0drBl3HXuXwx=JW-`jv6DW2XJ{MTOr{7CVluRMeOtOb6gxcs|~!0!wEaBKTGmWo(|{i?9@YH=U`_#kxOnx|k}rz_KU|zz)dxDC2>fvItl|OSUk7}C zPhecB8-P!p$4;m1?|~mG&g~EXjQTzBL&fX2o)4W@0Utl{0sO?aRlpAw&l-6pb;vdH zJ9*a)jB6zDL&eiq-$AQj14t#vludiafF92T^ zum12UXnr>ERdMqB%u(T8z?b!s{;a?CiH&%zPi$m;pV*M^_s0hIiw!qUiWR-rKQ`>O z{${F>*s$`XL~0bew(=x%TpsHWlp7-2t~%4#D?2ZO|Aw!HAK^_~L(bsB9FsO?*>t~c z!z|?OPkntj=LHj0bAaSnvYBPvEN7M)P@CV}p>)XA2SV`S3F_t<*?&&3Me0-V( zj^X3fpqwkne+;keB{=!*@C(7s@7uy(B&ShOYTLQ#_LB_pm;CnQ4CimF>2u|Yhubge z)E-}J5ABNvxIyR^Qidx`ugv6d!Cgd6cJ=z4$W2 zn@*0YY(3@WhQ0V^l`ea!sNuCW8D6SQd6u6Kr{A8AwVr%$xw6YoRc`J(KCJQ`@ZZ^o zVU=GCFa7c`tXXdxPQymSncZr5`?-#5R*toXKX@U7IAYS3%FSD+dDorvBtGvH-zTP? zJ87w5=ijLPUTK#oDm}?-Xg0jrTgA`jcPlxvndH&7NV%t1MY#%JdQu^9c4|2GWcWLO zlA{KxK_GtWkeE)_?lxG;Oy+)R*b9H4oNM1Oyhhr(#277` z4d;75QQjEa@b&?FqYXbXUl}(_`yNilZhu{GEBLyt#4x7eZbnzF0AKoXCfrEBGYoqL z_y%Qf%m#3st(;r9Zfw!8oQ#9YOAtpj#hIHLcz!Lhl?R-O#9HmhPn%EI^XB09mF8=l z$Ik?37o4xxI6GxKnMdY+*LY&K57B?G<#`$TjAa@zn$UVCv^@x%(tytNS3ZpV-ER6@ zr`#!9l|Aqb!@F{z;gq3Ir(9{+1J|i^+1u2hyc>HPPCM64w6SveLw4uYBHQrsl6AzR z{N4f|uYixiTVz|~I<}T|f_rj&yw`#^GPm$XpVp}~-thIzkI}oY6>h_&I(p{Y|Gl9lYV^pzMsoei*&b2*3Usm{Y-fA9A_1DyQ-1% zcAly9T~~pLQF7Gs%yQp_Qib1;ymy-?R1abB2cO z&5Pkdcur^nA4p8?z5YJ3J5}i2%QM0CoIdnNzt8kSCMODoK?&6+xR;-G@D~ zS<9o-5~uDo=siQrW4i2Yg!b3Z(DLYvxgI$L_uJoB&b+AMPKHl8k_p*P-_%*zec+YW{wv$nbtJ1zZLj-n=Qm zDedmfLoVTUcgpAJ?@gUwa4-5Z{r#8U-=-<_{~dA)KhyN~D0}B1k3YB++_^F?f#oF* zaz#!8{`TeaN$3aOj3F(Ti3@7k1NB}Ymuo}rOG}x{8~wQ~D-ZbO0Q82xhrHI;$sB5U z5`=23rNamq71U;Zf-ALhqUAo`(IDp|=aYgR<8cH@pKMD`y{9(M`be z=C8qarNDazzQY>!U#vl9HUM*ymQkmS9E^bC4@^5IyKvDdn7iuAlTBbjr^Ho$_1qVVC-F#sxZM{2cbl zz1BM+cBgTsX-~NyKKzk#t~BvmB7qLy1&@EC&?)_W9S%><`Ix?HHD5EXZlY71sz&ry zA${!Beb`f)(C4FcE=};Vr%Y#E1bLJ-P{DK4O@?zL`s5(j3B9qq%wct-^32)L8QZ=T z+cRSm`8<#O+(ZpWaDq)}(YcA+=zyp;4OcpqRdBJ>9D#HQV*y%~Bh zgWmD0w7rl#q_-QqhZ+66Y0#wVCFN|48_vG(U@zd!su{xL*}~)EyNPe2b>R%;5?yHb z8IA1$R>KUf3++B@eAtwojcc_obUx%dCZ=I|Rp32;l;N&eZn)+67CWC-Zr=y6EjOd* zu2zXtD|@*sR>*#pUiP*dl=sf54nKHb&Im#i+Z;q_&>nzx0IOayf z99iEF+;Vk!!3%~vpk29_v-j!kLxwwWhjK4I-SFO7q2aif|B`)EJ&1o^JJI{YA;Zfi zE?AB|xD4Oon(g5G5^c}WZJqNeZzs=tSBQA;!k$u={_O4jsrQL;-lnhZUxt>iGR7T- zU;pRIqn_7&i(yZ;4ST>o=<&9)FLS_UGi_dE+>M5PSq*tm6Z`k=zTO3mhLd3IO;_P3 zKa5{di(iaCuzV`M)Z5TyCuMB^a%_K4c5eT!;Z|g0hwiZ*^nr6=4|JOYZQg{JDzlv^ zvSkSz_+@#khGTEXb}ocp-hS4{VfzfjT?oGfW#|0;$~n|vcsFo8e>t$gD_V>FT#c^= zpXZ`iB(^Gt&j-Ng)1UHVt8#dH0J$hBIF>f9?m1cXaHG4^ch3whL z9=URN;uc^bd-0orHH-30U?F=!+1uDaf{<|?;<|Aox^5P_ZaucK4Zkmr&a4UiK96xu zL=PPjK0@E4AC{vZg0gq}&DcEbf%Zk|uli$=xolqt)%rf&fSr0w_GL}V%|VYr7cZ4! zuFzvS=&_*eoWDgmH^YlJaD`5qFY)QT+Z)ki&}m7af44xV<)VKNX`jyB0-csar=aX* zI_Sl?wnNw;aKa7`t3N?-(zx7bLWTHniUCN7wvA>{6SwnHGM@sb3{IwbD=NtDOd4%-N`4xlk_3;aM_vE z`%9;KzfjH#)LYO%e40nxy6EO&u_t6TWA--Me9zSLUaE0PW{Tg_kQe-{|AQnTC}HH~|Yiq+`@wEySe09`agl&^k+E zRMA7}vbXU!I!5(A;JVR84=x#3sd8@O zDsz_vC(%Qu$Ra z+x|t_qnht7TZRnR_p>j-2iS8i@?YBDzGRqTKY%>ni9BEZRdSz3zWt3tG>zWW$|`jQ2&xSyy+?{UT*#yr@23 zew&5J+N}=}Yol|zMToibXty6crYd*pXxcUFcHT2zpxqjBTJ?F(AHHBXJysY__Faa1 zQ6J*%4~a)ESN7$=?z2rf?+D(n8}{Y+T-|yYmU^_NVSAL0x=;oL8y)Mo{vHHZnYj8sXoy}8%FYQ_A^Vxc zZ-e@I&%jUbUjluY*U+UR`&r(tA>iW2yoAkIfz1${cVIJ?VKdS=@4#j(!)63!=SB2z zJ9R(gdcoPm-QadBapmn>@H2hc*Ln%rw+F)0Gus1Qh8-IS4nf&7XMyt%kCgp@r-9Wx z7}*DQ>tIeL26E_6U;Z+oEl`IRTyub_voy#QaJzPH`?K5V|x-@W8! zWc(7ty#%}7AK4WjztF&kN8WqyhMzNtTb2q;?ji3>-%xHvm>6s+FpWO$tJwZN!~$0> z)4smfm`}{t!|)~yXDp}7ekpXCj0?FZ-)Zka?kDV~e3s7diJ$1Pm(t1DM8Bndy?N_c z7w^VgVT+f23ch;`d)t|YeIK^?s^Qc@wy2|Z$F^S}%a8Yw-`<_O$t4D|Np8`;{LA2l zY|@^*C-I#0`E%twzZ>6T0{bIRV($p>iCNvPz+dqforCnM*Xo$n-HN@x0N-Q5F8qhS z#GN0(a|e|@#N#D(W9C&3W?JWA8!5HD+pzKW8!v2?t zA$G!Q1-ccV)*{`aG|f5ez5n?D2}#-U^Q6QIS7 zhBMD3CM?aAH4goL$<{*j8GJ~6$uGK+UwnNceNNH&MOX5RLD@T}6&+TNZ_gDy=44Fa z4_e#`-#1S~&L0YVqF({$B6Q?FU-xXem)tmdPs(E7@uhsf{(bN()^eU0Wrt|gao^;t8^Q51zzlke2 z9rlITD|w2MXA{G_`9JmZMw72+d@ghOq3nmqwXx^!vb$MNJXvCQ?E8(%y>F@E?SWS> zIYr0rcBGq@ZTA~7;?ox5{S}7$Y60=>Uv=E>zB~)XeFBS6JVa!93$Fhk2yW>0oy6{!pH15x%DeVM!&^X1P}WAy;FtR9 z&3jb2+jEG=KhW_wIRtdY%YNPJYD4k}?v7P{J|Ve<^_kw(J;=O~FW7Mgb+_uej_K)f zx;xN03o^j@#FM-i8F!C;w271Bse#7(*#AY$xoo1Je<6oxZ^i~KyI$vCoZGK3Saawr zxkYE=rHVWw`3z*i{0{p^Dl;6@hBo_;axmpH)NuDTl8Tw{AI9*SU=_+u# z9-BW6oJupiTYK>vd20eE7o0S#Ex-b&AYWx~o(ZhA9r-I~3_4{WV-(#YIVQcnfn4K{ z*jvfZv;HNyMO)UtmR+RbI1{b}r+a~e+zZ?jW}#261SfFZH%)M2y-(<51azW3y2W0G zZb7Hn+nSVpKYqZAVL0qdXAE$DNtTex=UmKo$e zTi8of+1K83Gk7h>A88?8C+40w8@^bqaZ3!Z&$GAvkTKt<#|;1Uv;T}NKd_X&0OWzl zv)Ml-PlSxx-z+lhoL1uPRfhc+Z0+*B*kxk!YaXRM%y92RmiIn_j#^?kV-m#G&l%3x zOQGRe=%1llrez+rAAY_s$Ie*dok%0RYb&Sw0K*B7HS8>l_%Ih)#E#6|1MiM9+`di7 z@o=#T{fKYrL*TL2U$nBf^A&it`xS=01sl8&S)Ta@aXzxVYzMf`M_-lp1vWTTb02x; z>Sd5O+cJPL9P)E$+s~rycE<87veN?mM)Dw!GKNO-cpHJ;+pyh()NNrdk>`b5;jb%* zvljzTkY};Wf&;#ai(R(GE=&3LAN&5xcyK%*c6kmq;A4^J04HFP1GLEjdefn~m=AV;@H(Z|TMrkzU*I z%p1TXivNN>I(PzlV_o3C)JMdB5#Pg|JQAGV)?>0KZpUvp%Sf;N*%Pl}Ef8L7i30~* z#x#P{HOMsAG1oIb^l)_)KWVFSlikoWKLIcD+%xbwru-PV4`@AzFWcLmIE(Qv@?{&F zXNz54hAgA!-EG+A`~IfbKhwvz)8x!^-Xd1N7@J*4ti2QY{ifj}%l7@dmGhn7;se2B z6PALi^#z?KevJp?u>D{_ptK5=91fe5?$Zhmt$==&Y;~^-Oj6O z)^qna2tRHDP7CvZ*056bZ%Fdk+vtRS`{p7y02{}H< zJ^WKAqZ@jwGT;T~ko6&L17~aocla}H1GSx)3I1z+{-o@Tc{{LyT!lZY(CbyeXN?bE zoVj1)+rWt%nDUw${%uLp}RLvXFRJlZR~C9 z@l(rvIN)w?TLeGO(r~;4v8s&cxo3PEf9`YS24dphT3*7|Hrk!Y+=)+xPpy5bzUUTk z5W8znoe56NT~Kz;g}20~`XN_v5?IdsII=&geF?EJ`7-;Gvx$i(81^gp)*Hug<^FT$qURao zyxxp|v&8Iuy!p==v5_nL+Lz~&+iD}m-AmiRF7G{0$MsUjx!?lsuU6hyE+9U>iP$>_ z96r#w1$W!&;P$eg7fZO*JsX{bEPsu-=FS@S7o9{*jGc+!LM(nJ?f&BDljh9>w-#U# zA3xt>c(+d=?mh{fN!{JH;Z8i0oY7zWJdgO|o6va^f5EtJM3?6iOUGF|u7S=6**D=q z^NH-6fEMHp+$k<_(6N-As{fYQzMtIpHkGp{h&r2)U)E%iU&~*c-H$Fm8F+gFc-w%7 z-s*sN74XnELD`!SHM|@97~b_OjdvF=f7>HQq@fFbM7_wEATOT@%mh$D*+?=5=?-jsFc z*C(RCC$YC;4>9s&Yz)_qy=8gi5;BPKuLZAP>NRqA%G22Q%k@4JSyy+btRQa3f8|{j zFZo;aN^fvNC*3#@oY0r7g=32?xk@fT^oqN*)rYmU8T>{chP8DD@5taE$U8CuXVXyD z!WrB9T!rq~PA}t0{GgrK^qJ%m)&@C=T5y`|=Mr>IVhK3S(YXZ2#BOrWneZZci73}i zz#*3~xIQd-0MB|7TTa}5FM37i61JkR&hUK}bhZ1^mDq=MzRyD0duBg$0+)SU#b*JA zV}jHCLgbRTx9MhV!*U<5t+xPog@#Lv+}nML7}>p>_<5qdH`L$V`~z(9y~y}Y%H4)+ z-iHs$x{|iVubhg_MTU`g`_JhZ`5Jx?MrK||p0CF5AugFPg&4L8IUZxUmwlPBHnC28 zHuJERD|s%Sx!b>hyljU4ZRqCS+K-d`nwO|yFGxS)?~jRhC7%5+V$?tDcs6lrCC~S1 z*zWe9;n$ylpYZ)Y0?)alhFnv9KX>8)*1r$2mVz$2>@4Eu?Yga5NNi0mT>5k`d(`in zby~?=y8}Lf=PslEm#P1%uJ2?lg_bW-7n{#jXzIRXgV#R4?sf;fHtV`xay`Bxb+^~( zx*oR7Ex$^+10E*-_!Mw|t=xfASySHueHi;?%jk!ki>#SP{-EjOosUf1yp0(BZSJv` zbYx}Ni8Szg1F&MiLZ@h0n}OwYf)xiA{RXhT7q%+zX6V|^m3W^sFZfF#%lpv@$npSW zdDkIu0`9;`KAgra;ItSxvwfWIqA%`w=OcGFHw#Y6>%Ie=O2Z!e3%qLDZ!h%o?APo- z=QSyJ1@r#SI~spm^6V>!M}x9+0eVaF?6+{epq;!0KIQ`E=(a8BgR9APJrd-)f;9kg z*#4fSU=4t>6Wy)vdE<-7E0J?-6x(?~)<47AKab#}Y#9kG=qKxSTegGWS@^QF9e;o_ ze7b^p56WKSbbNE-s&=mAUj>HKV+(Se$2#UrVh`lF75paGqGu*+J*sh0>Q0&kUW)>}$Zz*1zb$aL;$OQD=zTYdQ;h!hW^!W7$XB(% zgHsE!g*&x9v&m)K{oX)MzkEYhL&$X=llQQZg1xu?7{E#*W;Ks zgSJ<(7vo`kFzSoU_Q6M^zC5=@X8Vwzk#gi&J$C1O^!v?}&%ca&4f1}2DK=B$SbOuS z>|J=rhqaw~UxxpXhP9n}Uq*}{l%4a@1BYHTyqmb5f0o{3!#*4KvmvAGJF)YK@22BB zPaAfRn(A(Y^&(Pcc69 zNFPVzBF86=LK-Tc_Xobx}&_@3uFl6#HN$uONLb3snU4)%CBGvD_2cq~VcNL!uT zm<}xTNKkgp-v^u&dXnq;+chkwJ2IEu3Qpf;@6gYKJjU<9=^N+);t}XzZ+QSXKW0xK z<@v+F6WTOh%|3hhpMBg;lpID;eW(K`;$U~c+q%7b*>=|c82>fQ&G;?oN#tc9dL$@& zFQ7ke1{cvIqPwG8$n$_xkNu3Zw6EPf8@v_=c-??bTBz6D#2(p~&(d+Qt1S3`kE}`c zlXYpg&x#-xF2b&Ye=_3B?<+%)Q{;E=R}5F|?@!55zxflx72i7V9rj&pU~Hqob3Af3 z$MD8&le`o(0M5448S79#ua)9D^=#z22)+<tx0Zfl1x=e|VDT9HAYlh|X5 zKQkpCm;@@1f7GGfs{1L%7Lm%Huyrli0(ZFmzT<<0PvN2Q0A>P3L z=6#08{utgrFq{)+vi@={wEktV4*ayT7hZ1YcMD|gddCWKW490=yrI{pofqMicKG}P z>hyS1_U?paz1`_?IW~VJZLwF=E+#JrFDyIDaITn-oxhbbys+$1oxhW^^8tK&?o-5N zBavmUk}J4%Fn_ND7kno2*XNghj5qaZ=9&KXoUG$hdn!I_A8-oF&T}isb)O2nWsC`d zIk_|>SBb6d&4a-MnDMK~TfBsB`NCm1+oqvg9_j=KoIV^(j&nXfVS>NSob@ESfILLr zDtrolPkI8pE+$t)P9lXZpR|y;{0831@yp)0cHYM!CTiGE|1Yyg(f}9vEpTGkG<3>N z#&bD3CC6c};RllcVqF5Al7nv&l)YOfl7D%LeI(>LKIGc5XQPQ2r~$is4ecMrzP-%; zlc&Jxvcvm!E?y2!H~V`(WZ%wM=I(~&zh)FgmaM}q+=-7HW)D;ov>N5_ zYavJEzC4{dTkYpwD0^eU>4QbA)qFtvgZ#m>3!1^@$BYY`+PXs}MwIq*cTiqPnXzDF z`?xQY-@?XvSFr!9u(G#3727O1E#}Xiif!%tRv@z@@S)K&#Gmdfr{F*T&G(-#Ei~MI z#0*jEu-$#}0%&qEb50JcoZMAv4KjtjeQ^iZGoe3pdAS&zm+3tLiJ_(BuCRwyYh=Gm zf3NxjVzfMHz8{|=haA;tXx8l0Y|~Qg1+v|+30sQZZMIqG-N(5EoA4hTa!i|b8`(?j zZp998_1|4WPM0F5x*l@sBBv6E>UwM0W1NTXrHzY>wr*toZZxpyvjv$PH=8nja+O%! z-Fyu)$^6D|A$EQWdR~Ul$UN$}c{%NF#%H7~J_Yxj3l`v?z0LJ5-5&ku$NY&o_!z^` z%e%FIXJ3v!$vMN9Z&^#focJgQA4B9@e7hH?vsYlZ;e5a~faO)sA*VZ0_FsV0Ljg|Y zf)-xn!_hdA3rfF}B>23DEVUzd7htQaTG7{~`YJlo-8>XHy8<})q6>>V!I=phbQ<_L zH#`}P?McQ4Zh}t&`AHy`i5bXVoN?74i#yl@;W4g>KAeVD#^o}u>-}+2_U`(Wzk&El z1Hp|L&m$VC!)Z=MdE)!>IN+`b+-3xz zZbOQk>MYvjvgX;uxoj3^ceSb5$epqdU4T6)NDL`0Fi$oL*jqNx99}svF}!r3`8i`? z;&b%_%n_9X&@ltdQ;Y$LQ|eFR41+;(ZbJG`&MuX6EaaRSIVUCGlQU+vxqCdmDN1TbT5$3D_ zi{Iz^eHP8v_m(^+XX>cGxK{LsmoakAu&U^0H$4HZ4HfTYh3uv)ls(mWX040bO<^P6SL!`0^}6eNi^if~R~zZN>2|TGv^$Mh$p2yg|8Bn@%vKT^dG>hEc*ff&SPWi?bfTwFo|v@u2gqdd@lIoEuHgij%$YGRC!# z@o~1)5ocvWLw!b-&|1zC(d{&iDy9m2&Q1R4SajBBc!uE@&MGwF9l^m3N66U|Rf+ag&)I~&@`xwG#5qgh9v4Ibl=5zBv>n@6KcE@#eAaBS+8UzcPnvxIc#jKXQc+IA_Yox#RrUgPd0#iH)d?aGq^M=Fcq4 zHR2KUCg%<#*P$h+iH@mzGM-_T$o$E4?M=i6qRDP>Q!;|-7D9I z9Q%MBEq=43pN2s%(oduAr|6t*ZdK8wF8%bCencmsw^wuKI-g7_*5}jAvPGw3-*|`e z@!(9_pW;io?W!SdrIlo?Cc{h@?Jvftx zbE0=~wlVMR)rUDZhj(l1!|@6^N2jN%$ynbix-&TI)dbhUa&AtnfWP7QgyRdsS&7tK zRg?L6MCLj+ca@y|*H@qQQ<&T(=by#S^q4gNQ$#lO2hs+WOaqucr2=7#loylEU_BklqBG#(Wn#j~v5LZ?{4BGzdi7kon|bk}2ja5d)y%kN6d zr*X+FJKR(F%H%$@tKy{caB5f9xXk?a@OFRfeyQ=CCAz; z^Hjq;Vc+)DT7zhtS|K!y$@wvq(Y5!(E0Ne>BN7{8MD)E#a)rJ|Q#C>>&WT3%cFf1+ zf{(d69MB&g=t}=@`f%HRTPyulCF|sBS0^{R*0LQjR!Q(@uJ*swtsHrqnCTAVv##R|S{*_pn) zY1=bb=J{NF<@wkI&ZAi*=Sn5d7X8FNiBK(NeATHUzp)YZyu(c$;TW3QB1hL4E7k6-h%P&~T~`|}+4M1OF0t6JaF z<(%bs*7}I>e!S=UY=P;@`F$4j#kYZfPcVN5zK>*rH?|FX?)#Kq34F@i^}QtziceWr z+~HGVul;)!qdWK6(tG_u^hrjooX^!@?b0-#x4M;YEkt~sk{rT$bDVVzJp!Gh{Wh)B zWXy)acOKA9;@isj(5d(%Vh=R#0p4x|e$lqHZZkAM_t(>=M8)^6=E~S3>qE$dg-lq; zgk_#=SkNhqEe+$(ht1C!@=b?`$jLwCQ~To|+A)6c2*zK;_cX*$IqDl9Cb~_0b>ZcB zjukHcA~Y#m)+)AMa1Cf$z&X#yxL-0b-rdSbNLzTyPNJV4Ttz#082y3Hhfcn4@5508 zI{M*^PqS>{5&e|(_4_&UeqC?$U+BnwL???(LPHZ8c6{4|afXFvzFb+a#W+t%&oMlT zj59}?r@>MG2G4rVa4rqb#aBPpHnOZfZLjos-@#dD|5N&9ABTP?@ZFQ_Bgd7dpN?h1 zqJ!s(og}{Lq?$EP}aco-G{pGXu zLIw7rvtFop_3zMc>v8C}<^Ll6zSNah)%Z^I(>aqwAwJT*R$wbrJ;j#TRaT)sXII<% zic!+WEJ~q!<)?>r#9=bcSJ?Md&-xeFfOGk@cJjPrl=!XSJ?2SI@Ai+)b)X5YTlrTxEs z!MHnOM9ERv;W9a2oAHXS1D_)B8)o2p82%ZcmW(&8r`1=@!g~CJQsNr}--Nn+PbfCH zo-5-W%ysj!!lAQHN+)_|)U^hCx7X)rya$n;2n?uSvjlH7N*eiaCJ|V_flpgD_ z*x;nV?8u1$&k#H0kF_EgtJ)ci^)r38;xh)Zzjxj)cYYK)@OK+|4RRae$Jt5F%OA0> zHU3OSSm(dQFV!+#@<(!5-F>@vJl_*uE788=b%KY`L;E(Ix#|B-p6t{4Lh_EKMl8Eh z)nxMx7koOQX>m&Gr`{9Z_3Nij;XXFC02;%O@S^au@TRt7MerPPm>b4t%)W=S554|J=8iqL^{V)y1 z&rZvGe`v@#*;c6Kjzw=lL-?>>^J~kytKTB_`5>6zGo?TF{B_Kg_`*`R<=rRVCw6*Y zWL?v!FhyLLL^nuIsZ!@EV1MPSem1eA+f3O;_o6ARLP3xB3_MiNU9GreI)L_Q_9 z;cWMqKHL3_V}6HhqJH*7z9ZK$&-mBG??qo6m7jNYe*S8CruE4YdMZ{h$dK=riLMe| z6Q8!8@ep4uSlvY*5no7NPV1z9h==di@zk`=Jlt8orQzlK_+A6>ylV6-q6r9J|Mz5+-2zZK(|D!vyer@jT8hrOU)G?CI;T9 zc{y69pNlWyivRB0*xqvHbd5nAt8GwfWAT1;R&?Cie!b6!{CX-+<}8uoEab4@Tf)5e zM8B38OZ2!aE+nVd*X5ZnZ%MwtR$|C{Mi3MIiuDn4N`uHF4Kf3~N_@OhC3b{;kdad6 zf%+OR)g!omK7n19KFP0ePAYX6zu%|&D*C3Ej5pr5IZN9f(a(`oDR~xR;;*M;lIz{b zT&;gyi}6XFXxZ6PN5&ZRli`oQtRxu!IX+Gu_(Xzw!;t?h@|x)9G~JUM{r-TZZAD2^ z_Yv{?Ko_KGeTomGu8i0>B6H_PlUk4I`j$0T^s2x@w{iWt5?tKSxH0+~Y4GPJW8B%g zoUvw%9r+exL9VbhT8{WmlP}v9SNZd#?e;O_J&|FTdGu{z#Wf@bK@Q^iDzZ@(%<~b9_N3DE}6|3GRe)b7Ldu>H@P@;F>3+VA@dRPt@vt^ zvyXpkR1f>4FDkFwD#J$K>iqxeusnm0gZ#hF2b9c{{J))j2Y%mJBcAm;Q(z>9f0c9Y zvo$Q8|A(*rbp`VOTIZHLDgDWsQ2Y+Q?S!89teZIF)gQaLCR@edevb8u=SuXryWQFD z-f@R&$?4{g`&$oZyL!A&sFtjU-*v)#m#Gl{^{=B&OcbFP@MUGq#;Y0)t(%$eC-_$0 z!zC?!GvC&E#14GO;rRIcGQbC$QvxhQ#VWLZ3**Cu6GKYF=%X)Qi7oX+4S^NW<~@HF;s|A=Y9Uv&fEJl^Q2=5y(mDVH;L< zp3l$N4EQ_kkK#w2<@-)XS~fYayEKrYIvv~ka+Eq>zGdgbt*x=i8T9w1fPXuD zVsd-fwLy9vNqk#$74~P4&by-%FA_h&mz9$Hb56 zLpPocG2$~GX8y4m{nv-hhlvMPA!miGcUi|+zvW(_ui&*h^iv74n!Z=ZcYaFbJtv>G z^d)nP-O#=^{jv9m{F&je{Yf5B>!(QM2Ki>D$cG7k)QX;{8h5jkT!T$PKO;+GPXaqx zP@BAag_~T&nd<9RZHl#uWLcxcAGNdW1FQ+W85_*+Le?#kg_FcTl=&`>3sh$^=_f{yd!q*{D2yDB-)WuEo71f$HKuQO*JcmDp~ zy0y~&`49eov2Lwxtvc(o){4`-BD^T_sMoDEjnp;&)^%%*OUbCu!Ug>zK2%8a#L@Un zPp?~>h4^DdW%$orV-5H}rnKu4Ut){?7yY)9#tzv8Pvoy7E=B$X7sL14Ha>eKUfRw^ zs@mPfqtm|6WAOzMbVY;64{}-6-ZC$IC{f7w8B_&vi9%0^zD()n?)`I{qp9KFgmqADi_O|2X?$vf3I4@tdj3!@@?ZxZ1?;R z1KU07pRwJ&yt&x!Tf^CD+b!oaxc8k7uF!|?x8TENnJ1?xC(%#I_LhuH=pz0k^pL#* zzAw35+t1|b*w3K<$a&~B);6!%hTYp%A~w{$?Y4HIZ_C0g--iBmRbWGZ!=9E^nF^X$G3Ox+>+*|%LKFNp3td>_8h zK5*S1v<(%VX_ejW$7TaFm(K@x_(~kC$)Iy0dgZ>(i zt83w{F1E5GcE(l~XgxdZn6}c#aoNAmR+cR2kjG?NPSlg6j@wgh2qbLBeF-uTs=9!Js1^&WO`pVb2 zeD5?T^Ao7j@yWrF?>d9G#3DJA5ArPr`Nq>nTvH#kyG?C|4*#abXTG=zA~@b}3i$Xoh#RZYOlUG@|?RVfv}azod#-MILl8=LIe z(qrQrlK;@y)b_tWwu*cH@v)UGlDaaFBbk;am86e^CBjOHb<)fgv(clexZ?XCDVRuFyJ@{b_!g{R<;jY8@H_ zUwyC3{sr+(1#k5HyCQ!T6OYAXHZ)6&_46I*|24ra0{+plli1_Lnlkd3 zDdKZ-O?R})cWA?`_lN!Zsa2wf`9@-xZzf_>BlvFPco(ot=Y(U!knc6sI=5vuMvVmT zO3RqQ?@?`=G)+qq(*NN$#&Oz|{qk@dRiSat{oSYNt}Asc)5iX;WZ8Zl%QQVy&t8@J zI+jVY*DIO(yL2p*9y|2OAdiWjTdiVYVnXy8W683c&_8-V>vVrVYZ#txYxDQB%5QQ^ z%D70FmrD#rKDMDF!in`Nw#kS%-3XGGY$ zThDiP+f4X?y}ME`7;CePRq8R;8GMhKdiG+*I%y626e83;+%6WCcEMN|GuBDXQir{} z(uT2iYSS4;EP5D5jfO$4Vn|Y%52tfCvVS)jmi102y?-}?Kj72hdrp`=IjiPszK0&i zjF~0Y)^U)uQ`(35slb=Kg&*Tae$^$$jYaTA^i=yY*cYYij8dFe zLmq_uoPJ){TkM;}AYI$lB6iHruT|)8 zp37ceWGdulN*nB4I^Oo@ZH)LY;;+d!3y-f5R*#{hDi%yAx|tyJd}0 zf9t%em2<9|*}EDI$5y5IE^*WD*bwwqkzNn)@NMA}KOUx!mWAPueA!OVNl8fP7SJf% zg@zKJM9O|E`9+uSU{a%>hUe3` zFzElNe7aAoWGj0#y0eDLnn%6l`wy?bu@>z2oBVIz2Po)>`GC(p;g$4_zl9HjUq)`8 zwPRT?&gi^eY_KL*pUwq;Em3Be61T(}cSw{u3^DAf?Haq2;p{vd%lMiIvjOEC6M@`q{i${;! zVEy6nxC4LUCG8vd^zJV7E*_1aTNK&NJ`#8p-dr5fKC2r^4yJF-&o(ij_@Yu@{$%YS zQB-#HI$TW4LWanhzcx80{CDb(PxFn~VLi`$}@wZF@6<@okpz*^$2na<3jWiJkm-tW@^Ev)0G@Wkz#EuL<^T4*BbY z%8chUGuP+`Su6ABXPHgD+K11+OWzmZsybqcKu<2VtsE_*u}4<#7I|h4wOwUwI*(_L zL+6Y`|BNprrWh4`Z>E`VoJHmPE&BWiInS>tYM?P=w z+*~VjU1e=0#tPQtEB4EL)V7&VxXJRl+P^D*cLDk75!%0N8#TmD7WUBo-TL>qpCU%| zbJd;Z==}6Ncec&{EAM3ab|ul7@1a$PuIk7eYTG=fGQUM)H8Tc&$BffNpK6^hI+eZU z=E=gt@W+pTEwULoYOm>a5}T+W9<`@T->b3@d25gbh={QqC_q6`@0@K&J$az_tp;vPw9ibu(h%mHq~h_tY7~+jo(rC zE3ToxqxN#f3JQ&QD2&XB&S70;++6yR*oeLVqaM^(k9Po^*(tHR$Dv8xmB*$@$xN|F z$D)ahyCv^o*2+XK6>=*61%KR+4SrbDC^qER_|eaaJRFtdV@`E$&*yFS&>j&J+g7E& zr%dNWDw$W-w23kO__D4sfn1wq`1jgBEqOVundE zVb;`rzR^5`Z>0GKeqm0J!z*gsamGIue2?0zE%KvzrGJ`NN-W_Svxs-Z3W-ICeR&T6 zA4B+t^B+d%DR)Dz{^m(+$iwLV2suH4!8;=lViWXx5ahD-yw~v^;Q9X>{I&83{(7`4 zf7PY=F1-iff1sa^%U`D*hrT2K&HQ!pKgnN3$KkKSe=~m_{Vss7p9lQEz+XlGcK-US zpPxR0zYf0xp!HV=e@zJVm!GR8pQ!!iKMIVJ9FYZdYe$aP*QI5z{=>Rd*VFHvcImew_V4Mp;yYdYRX6^feqZ_b^sBDu+HZy4r+R!kt6l$|ek;DwwO@5r zr}1{gjph*Mv@mQCBjVdU>-(dc|4Xp7#OqnBxIfm{hpcTN6T$=9hr-V3SP%b@Tv7>j zv@hE6EdP4(r#8Mxy)OM>0}NzX{0AeZ@TJmzuh~(`>aw@wT?gK&P47p)Euhr_ z_TXj6ULPCYb)yQr>e<)*p!mEYJIed+d=K6(PZ=I(i`4XJKIHPP64^T{c_DXp8{hg; zX3JX}K5;Xyvsecqf2cB?WLrtRb#<`bQT8_%-`0&3FxHH;{l5;`%YaUqLQBEbt}1&+ z+6H-}mj4C(%zpyE8Gi@AZC&t#KaZxL^66Jz#<@M8LA$rpw7dKtq#gS3Gij&(_;1Dy zy8WZL)m`-2xRo>rZZhZ0{ZV;XH*%d`=e5yk@i#Vv>_tN~ZxDZfB4>n1%sLZ2TRe*P zR?0#@479B}E53MDxOlq0mx6Bx6wlJX+51{?Qt*2xYbyQaH~zU{=k8bWZvdxI*DK^+ zKYLcBXS}D?*Pfk+Z6F7nM6VR+9Of3Cla;d0|EN>McHoO=$Q~NWyV6hZSlD2FhV=nt zMfMDmONcnh)x=uFuQtyje~i|!22m5n7g>aTqF(yBy*SKTM}r}2$>uoLNEeSa+~x*k zj+|rzxGb5=H#Qp$r+O#3kf@4TD^(5onposdswVQ9oJpbtmfMuW``}M-zD^<66jyjp zUz5Sr;{2`@Yv=4;ZO&D-lgi88s!8R}Y|h^3lq$~a(Zi1He^;Ir6I+s7?Md5^+q9bVEOzo9-eXG6N{N5)M22mBThF1{kebar z&Q3HGvbUQ!#ahH3q?C#oO{zwr&!}fd9%OBpKdVEhH^;1nj8*n9l!Su$niVU6?m1!T z%3rUr%tb*gca_+4oj*zpDebbCQR~D=YL@6VJ+FEmD}E}xDDP0P&P{$x<`i19$0^_Z ze|UQnz^JOTZ~WZ3vt<&Jz_0{}av_mLAk3DT37{sDu+)fAz!gm2q5`6|iWREuOIs{ddDSW|EGjbJ?>YCL%*_Qt>i_%xS1*&_ zdCvNr=RD^*>m@zjMlyQZoa&kODAPXSEIPkxWf*(Ef^xX9=JyKr;+Q2`1EhIdey#!M zyuvMxe)5HdQrPauXd7eZYamX`chIwQAQN-2XJi2GZ<)cIL$1fZBZuTnPUmNPV#ys- ze@Df~zj@{j$_mZ#9K7GYin`-U;Dq;^5=i(b;#{EQa*!M2SKg#F2X7IyS=e2pIA z7^T&Tv}h~}UL$Vxyb9V>N^JRZ>UJ=5@mBj-r}+ULuTfW%!y+S3VYo{*z0~X?v`rBS+DzX*VK9m^Y^${2YXy`=1lCRpg9ig3Bq~wH>B9@ zL)lhGU(CT_pSt5&Qz!O(JDYG0-;Oe4UMGC=Df(sMmL#l`U~LNPS#3*D*PE;-W4i`I z9`-?Qk74iJ0PN$joPaE;3^hbPqOcd9_Ov`sp2k{AVh&62ZL7Z3{>%iKW+NOTd zneqVS2z1Or%j0LT@K?{s&ZfKRE{znqD2dNYccwg65Z=A9AL77$Auave#?C-{T`oC0 zl2KPl$Q$CsnwxVe;$@_R^A&0bSXV%L$;9i^=EbnS#rM8pZ@H;$Ec5_)*ESA%V7!ET z{Lm(~c{4fd4d?)*(*c>nI_-~+3;RYWRkB*9 zlrxlxIS&r8eASusSV3(0VAScianwz!JTisaBM(RRJkD;N!us)%m<98*L!QT-*_rtM zE8hK?kiG3F3+g)s@~5ROk4b{g7=ZM@kB3<@_EV*F@m0h}dBeQ}pPoH$`AOsl`8(V; z@~v+CqVonTWhBhKO z<$>sfcjk9?L?O2_+WlAQPTO(RvCWQknRHo3ob_L)9h@tll&4@W@awN6=i;yBaNV_L zdCExK2aG!z8@`rt4>Zn)^po2z#Tl8{d$>CpcMpOV`|2yXv-~F9xmpe#@l}dbo=SV3 zzIDnY;V%sL*QhQ|IAsd=8t$ZDO!VVn$Di$OR_wR>tJNGkb}Y?lW2xaoADQu+7C!Ki zS)Mi!Yd1*$mg92l_;H*oL-+^(4EqN5#Gu!4kM}&>H~TSjE<7gFS`LkIwpyXbQn9W? z{ne2UlXuA$CL@iQm7NS9_d zeB+F)rXy&s82Z4{w&_i@*Mw|$lmEvprcQHyfiqdxZdp{84e^O~i*iC%9n70s*yEmp zu5zF~;G7|NPy`;Rd+V{+9`g_wLoQYAtFE($U#n*)(ayT&RA_&T6LlzW?tpEBI7UG} z%m~+kdev;Rj~VRWb?q$ct_|#oySV=5^E7SQ1;k6ShrQc;NtQAk{VDc%pg+LbGU(?J z`cw3;bjBR|{FXzUWR z>{Ij5LGpKQ`KPscs-JKQ&TH|pXvYqxHD4RoOnHFjTQGl=Lk8yDgn~(c_&; zkVnLaGlDn+Dvw8-9M9+I`8`WyBVgb9g|rXKd(Wfbi^O7mFjh)ocIWbB?B7w_GsZhO zWAPmAc{h2JCw0lVJidUnjhApPa!f(z@)_upF?Mh~oh6eUaO=^uF!9VWnCi~fRx}u6 z>hI7Fu`knlq)&L^)fRc`7|`=r?13ontN6IuN`2g$W_c>w_<((wCwsmdz4Mce$S3-; zB~NEM9WxO3c6?6|@eGLKZfII7g#9*PC%$vG5wcPs@jYWp`iMIYK9`FMa1QB9NuK&4 z>>0}mJ|7Dk0QpLz`9C4U2M1cd3V%{Hyt89I=A)A_hIy39sDJd6C&O3M`gO~&@Q_E( zhka=ZpM02kJ0?l8h3H4V4^O3YuPx_=A9*;F>@)9@ssgGzZs!fO9OC253tBOsTtK!i zzn{R_bSy0kx+UE20h_ZAvlFlJi}7Ru?v#*B81up(#>0q5&XOe3nblanqb?m!+gYZ zCU2kH3OX%K1>RiP#Aw%@ci=Y#VN-6GVs{UPtn@KuS#FlYtWRoN5%jYzFU~$c#AEmT z5O=1)j)vcZ4hx-I_%pY8KYHYE&VBekNwUHYGRuDFK8NI;g!GdqQGWg>Y)>|Y7e5Lf z&gVSDUcm3ef8Xf9_t6WWm!64D)d>vwWTeK14&yQ{w z;Hx^fVY!9RZD4Gq?HT+N&24a+ttdG$-a#LQai2P-YH{oQIJ*0RE@gb&#pk=#eW{Qa ztq&f=`|j6Dpfh^xXXQ=M|xXB4(*m^}+~EFJO#FeILqy)_zL#O|%a0w4krD zrl&iTuz!KCxv`hzqE(Y$+X|JZ6~Fx3uh%+`NubHKT*RF-(&62C5Psq zjO*~-iP@0LISIL31i5syGJem1w6)=C&f}4PD&MB%FoAIFRhW82oB- z`MKa5<^7zzGRi~;>N1_z<#T+#Yh)20i-@z2Z6jfC!HxIl=wH;jmA&9QUz>MYJ7Bx) zN! z70|J7kk{k(H&8BorBO0#_JO)D0PCmfJQU&>{VsS_06j1EFCrgEm-ek?(LEwN70@jk z6L}~~g*)67J|{-{D8}!X!`u|VR|NXjViWC!pOr!Syg%0VNbr4oaQhZ(B-R+t4`+>_ zJg2AQo^clbXs5Z&Zb^6Ak9-e3n;yP2LvFJl#k}Z|v~Y2TB-{U$7UQ%7Y2h7q%#rR% zBc5b|AAG;JeJcExknRPIQMo{Sjs@()nbU4Z-X+Pq?I`Qqwh!O+%z*9s3i@-qIeh4- zcFy@rlpVYrvEJNupGx+6Gv~)h;l_Dnj-hYCUJ=|w33v4Um^;rTJ~}Nfq|Zi%PaZ=! z@YWDl4DAhlJnpU3;=NE8FXH0y=75enI@NeP($#qLsa%TJe}s9rZN(lcEABV2VvXx4 zAICZE=$8ti6X?8l&X>@OuvNa=YIQDoKi>HQ>^|JH>^-pyzk^u#h?Sp<#Cn-R>qq=7 zBbVovnIz9%t3~Rxf=5es<#*b^8|w3rR@*Yzjx?XO^mzQ>?hj7UH%4f#FnsF^=1$0S z8|HaqHt6oX@0)2{jXP9@?DoU_HRf_58(ar&Z{X=z5XK4}cJx?U_*E3 z*n)FgD1+*s?I-_j(_ot%J1Rjw`p~#HT))jMPrrbVcb&~AWE$Ider%J%pAEqMIk{b9 zVj2%)525V+7rrA9-3PnBFXn)r$GK9-$paN|I||;yZg^l9)=D>XSw@+$W(PaBW*@#Q z@I3S^#*)imr_TXza-p9(Fpr9Pd&n>PX1)&?d)-A{;vOC@Hxk{esmT(~w(vTKd{Le6 zqqbEvlH`ZW7v0aQwzo}G_goG}JZD8bnjGxRQ01TmGQA#moAI++xC8Y$t|Jf!c-O_> z>xf@JW-lh%W{)VGc8{0hb_B%_!M8t$}$f6$8`Gw5H~^;mDl+&TQE2w|)fVU;+I<99h=TB$7jCuz5->7p1=y%n9Be!9kk>2+7a?I5_ zIKN_+oyZe-tmO&xRLq^jj$M!QC=UA8CFb%mr;oJxoIdm&&8-t}`J6wsW$P=Z?&-8N zV*CT!Y9iFsda;$V1{!WvecYbka=Y6Fne8aB5n|4rYyJ8r=H+4R~|CcJsSEOM* z{CK=G^*yQWo%31S+o_P9UGc26kK<3U<5CuTU&8(1@q?ed_N~+AvW6FLHaiDdu#PuM z+Byh%Te@``zC~wpUNcCF+48NO_}gnanvZ*`F^+&g>qqgeHpuJJX-B*rn=ywrfUm#yPlAWgb2iw{i~q&-ozn)o?RB_YzZL{DWoIAE0YF#vG<8 zT=9BJY|u#PVM@DWWarXj7^7n@V&5DoobeI(dIa@cH=b;NdGj>L=QX^ap}xmCa3u9h zkbRVQAm%%-eu2eyVXR_(A8p@i29L)RKf;H$g17kF#+cW#GoR*l)iYtca>C1AFnR4S zFnK!4xD@?GFiTH6K&wW@T%3ixq!EUqJW3?xOh@taD_p$1iO1XZb$yHz+OC zpV)h+^*QKE$R;HJ6c#oi&yS^OF6mFYSAhB!n&(sVm48AX5A?S1e-rvHVefHURE=ln zO~&|fcQE=do)Ms_+dFa*{@+0~zHI0t4bK8_%`RDtN zzz1$W;v5QWS;RLIb}YWzk~R86n)~B2k98fb-`p6YzFkWzB+?>zqcUJl&^t-c+;*e8z|}r^BlR0R?;~KFp>Nmt96>m?GS(>CwEZk? zV_qRWZ{qs7BcjRGQ%rt>);lrZ1p5(v!I{HgUI1Zxw3oBAIbNE>mWz;2tO3)U80<(> zmMJ1VVQS>*AdR!yY*<$?w_zR^X{okb68cJ7GoZU4us4_QdD-{|=J#e}9<_+?XLRD+ z0?r4eQ~Qrup09)~rsLZkm}ke@*G8;?Z4&DrM=NPgfq2B{>IPbl!EWb!WS&S4L1)d7 zWgD>UhA3xqGycF53(G5_*VaVGh=%ur~(xvyfb3tc<-i zkTtPZ^$6ruz6`Ru?MXPS3K9{XGR z@w42^k^c(|p)=oKA$IvS(>WakT10y zBsT+9oq|2p6hGhhfIT}DC(X%bnOF0<#w=yFXxnGif2aeof2rHLRhBZGuicRi*;a(T zAlM(t>j3SY;wPEz#CjNPWUQ^MMjq5Nc68=ftYPqVxFWP=u@0xLr6<~mx(-M2lANR6 zeJ9r26MhowaBA5$aQPOp*OpyiT!-w1OhFGipa=0{zfwP8Gn}T!(yeCNuW)+1dp^PZHjsP`;WA^M5l%M!mc9AhBTD|{?TGNkDe+DD=4u77bp%%iz&i~(`q$4|SB zBj4k96Gb7P2AlpBRfluC81r1*rk7x=s`F4#liX*!1dp z178pMk?GX-KAo1)XC9;UraYF0-lxMxXzB2C0MPe#?7^_3JtwJa(K{vQF$-V2!MD6j z&Z8C+^r}_f2px<1a*`co#rlHEn~z|prl76!Z^_VD7Uxd2vji-$7v5^v3!iE+(>Vgn z3Cjnu7v9Ow5tRPG)97s++F1l$9NqVID*70UguNWtF9}{{5U-%) zh*#hf^bqcIZ?!`Y+2t`3KmVYvw@mpH_t)F~ zg<RT-ywPitSANgroFz;2{n+s1a!S}?OK~p49Fq-mF*cSG!@5KG z(8qKx27Bnx2Hqdd4q9#BIR{O{nCUR?*tWB_Crr%w_SbReO^fk8;V^6a^`)#cyqI-< z-HC4lhgs~kQ}Nh)4NU&^T`czZ8hm5lmZ(9SrP^vQKBRS5L%af2zl~hb!^T=zdb?iEWs-d_C@6dKh;x z*iLpfy^eXYrC0}g9ecrFV4WTNa8|$~(U}FFmNwTH>xZ_Jf_-*&>JPxX_wJIM15q~^ z|HZyOfiJ6Xm%O>}N#3`2GUvtT;tM7G;Uj|{!`X+v{UgfoZlpnsDzI(V`4ljAZ>U@7`fxH{?wsauI&c|)B2bW+! zqgCSmiZMZ)KhSJs7LLkNd*6e&=lJK4<4_;^WRP+nCZd`qBETX0=`Iyo1)L z#M&w8aLs*j4CPVBA1!OiorkmTTukLmthuP?`(qYn3NOU^GQmde`ds8Zfk zQ4y_Qi}*6(XAoX3-}Oy3HPQMBx760ppHSb_(5U;Tx~jZBRKI9KLt{kC)Px1K5z5#O z#4`zT+=zLrZ2ZokNopNmnv)bZqh=wP7n##o5iF_+*G8&p=5_NEadi2)w6?bTjDGqj z{7k6~)eApb)U!kLgbR|_r{9kB3%lwsT2QlSW^LoFrn7j+u;%Lph#>y!`wF|n%SBQM@g4Ea7*7IVOHr16j*6P#T3qMh!msUq> z4EfoD{D1|~%c^Q3^YPBAT@Y0!U!*kFH$`XG)K)^#HN~C>O*y- z$CN1$zK~Kz{>l_2-V~i(zi4WG?Sfg=RpDq6CHYorLM9`Fk(L(MRndl~>PBN+HA)#m zX>qYV2uqKIcQ5|_zar1kn#TG?b+uJBja+gX7Bx_o8YWbRsv99d`#(ebLV6?cUX1tu zX_{JFD*3m<%8}Nv|3A`P5M5APzlgWt9Z0tVY3AU?^e2Bpjg8R-b&b?WBUKBlB50qB zlv|_qwY_hY;oADB%3G3x325o{JUMpV=g?tD`zl>|xBzaHhvLv8C~)4y7DmHLRRe0QR;h-HkB)(2jn*g);65~) zQWk1}a^@XHS#`9cQK=8r%!?w^5e4l%+N_jB>laitG@xl0Mr*2~k%CC19!jZTA-WY_ zminrBm5pUuH#1RjxjkNAu0IgW3zdf>(F*qD`3iERw$o?u_y3hjIZMCOenjnehz|k0 z#-5-qR8tj(BAW-16a4Ol99>%5JUOzcMu9%QcryB((1K{>;?GJGb+D#fVUxoOyEdXQ z7FAdoem}TXVQcO{9}R!>ke=Gmp|F#!2nRpDTNGAzm%^UKyQ5uUVCvM`rkcp?D#U(8 zQ=>Avd{JYxK`D%eBGt9w`Hhv3pNKMQl%kdbA{A;>CORC5_oXjk2jF)HeyRTdgkKYW z_u`k*t*LE{PE^okDz{WMRw`vz&6zd3^wNSUm(9MaU`o+N?lM&P!m9e(ngx(n=xW#x zB&NKXH`G;!7D17hhmeQ*P&kSNPaxizi1!HiP5p8^5<4HidY;(9lXYbZJG5Bo=Kd`3 zA@GFqYsP!~-Q9UK_W^}D5=E>)>rqQQabl?Yme8Vx(oi|N!_i~LDf|zrP2vINg`OwB zQkWaR8o#(=C$E5Z03j8xA!!fXy|vHRI8%p*@@>7#sby z!p0+9MW_)CAAD{^B?<+QFl?%7sv4_8ux)tK<5Uj{!j&OBj-hwe*BRrfzlFp=p?{F6 zirRW^C?QJ@_9VhjK=>XBv=}S-Mqz^yUxS4)1;3%l!cYy@IaRe>{Xn+M zql;>xX&Nh|RrLzY4_Gnmc7z)R{~~-7!uJ6-wq^9qstuZxGoh)bK^RHG1Z6KF9;y>+ z50sBYHJol=o`hdvUp}Mb%l3N}wrVBh^&a$vwe<_A|EpK4jZMZ`h&04I8t;@^7^7j* zqE|&LNM`g74bjHwwGEAP68e8;w2|yqolC-h0SR|B0&SqVsVa9y4a{{dTw(1kHJ8@c z&X3lVRMkZbs!1;_Dr&B3Xl%Hqwy8RDDTxT_=)x+P=Z)ylXEY@K?s9~WB6Q}9u0rrD zYN{7aB`bbW1A6$xU&Xbxb+aJTB59&b57k7fqna%{qo%H@QTw|P(ti!v?$^U2n1ys9 zW>cH0tC7&GXmmcQltj!|Hq|zUikidGXe1gT=h?Nj#neH;_N#5G4@WO;YCxf);ig6r zkX)wJ*P_E}D2y(I_0WJYmxpQ=6<5{FZ_qM9QIUc!sGrwF+N>CCp{Q$X=FOm+`ApHmY?d!1KX57Rrsc)LhPefPynbx&_U z4O3g9ew^sZcu6Ob+=^eKQ#kTZGC2@0xshLLZxojPrkBP!M5CAd6P>~krZk;+g8*us_Cgn43;C?V+l+T9-iPr%jrRq-Q$YVce&58q7w?C7KgD|julbn52H+iq zHy7_^c(1{`0r8gOcRt>Qcw6zV!Mg$Pvv{|F{wjX=;N6e+Q@p3}CLLE;f4sx-j>GH5 z%kE6*sL!Bd%)nGO(plSEkau9}H;ipwuV0=$@#FN%euN|aBEtVz{gU}@@Ab=E_!aua zs7KmC6M7`ln&88ld%;)qjl1tbJ#teFCY@4Sp_G%A&@hp-Ch1JF?!uv(np)UyXf5>( zRSTol=&-{#H=+3}3z{0E%_uJW0O=_BHS+XqdX$t%!vr3j8|dcm6y`_x{&-1Ni-GBB zXoO*quns1Yyw3)WWF47;-N8qVk!T|<#s(#XJk??hi}p6|>=sD{)CO!y^l>3&VYI%y zwgE#8VSwZ~>Jb06h`)MSqOT%5LXXW2;N1$?Snxw_l4NV;%?fL;R~Q3tyW|aj3mva_ z*Ym%&E?Te7rZhB#$$mio>Z3GR48dNaZXNviUbVe`#84<4t*)L>ivc|`I)ZpEL0v2r~eF-@q^F$!=s|K|c&S#c9kxj~oTH|Ddo8(92;gk&Jh@lY2X|GsdnOnlvv~ zp~Zg`ag$y@qn)R5i8DW8>tiw{QeRu=V5<;^_iSMkqdAo|6P5W<=z<2NsR2EhGW;Ut zvZCusXBEwyeRV;xgS~~grXVhnW6lRYIlo|MW5^0h>SBpCG z;MdhGa^E$zP_dwKLQT^G)&HO2e<=J_;T=T&T`srFtSzd2W~6?e@66 zZl62X?RN*0Z-7A=XH7AUXR!7^?7r>es91V^yc|oKDW=~ z^ZI&wl}_2&k1gSmNrm*4I8_`QCgKiBW~2mC>QUceP_ z2Rs39z!%63_yd7JFpw8?1>HeU&>QpxbA$e1AQ%khE!XhJ=pIejRhxZ$J;fo2c7vwIwu1bwjkB4d?Zhiv~!# zM&KOa5x^7i?tmY9=oezp^*d34ZqsP=3$bK3|4-CPZWNp z+95LRA?hP+k{X{7-d@ZNkRsBiN~kBMZaAc1nx|gvr!fybNvT2~(Ev{kG-Eb~`tUNw zW+5%I+it?|Nc=wYrP`OZ17mu+D=!qZThDI@zXkpW>inP98ld>asO%8@Qd>v@)5hVq zYjDhG5)yi#t8SpUX|4(bEdE;>fr*c1rI?2EaZd^2pz)8ubMZIjg~>QCX;#?%mNIsu za~>e$`_yt-p%B6Pgu$cl|8(*Wt6-fe+{W z`k$d|K07r0x;=;2U#GCouR9{$c|EIRHir9pBoqFVrYE}wq)Sno$!ao5<}B&_p*JK? zOiGe6%o4WqNtUtlWc!5~k`h1wv)wGoHizjvX(9zT+u_Aw8X}oYd6L;=Hko8uI^QHq z$%Jvj*evxo4YW$+8*$quo9r;1FHJ(&6oed&=n<=IktMUul+0tLEFn=7;Y?E=@+VR` zPns^7B}6XSr7Izi3bSNIrc8rPW;xy52Y*_n zGzq+y&oiBm|ME?e%`Taelce#8ugNq*S}2=MNs?9mA20#AwNZ>FyVYTmT*KUE7qCSd zos?oyP)JD*f{1|fM7znfMwa?WHcC)7?aF7;YuLnak5r~GYn6$aC5K`vF)@_MEDbhU zq=!sH`t^}U+6O1+$S#!4WEv$+0q0Go6qF0+Vi2nd`%)$8LX%zkoY*EYiKVBfqsdDD zlpetHD@th|Et{o{h@Y8C4dmW^w@MtRxMTQf;#3H9Hk%5OEcCMgAnyr^uTXze7!P?Bw!O;s>Zv8I@{5Gcg@S z%|jxjRY=b)DUQ)rUQ@UZI|mF$BZcp)1|lnna0M8+9l$69!yFLrH2%v1%G-jD( zW6~w&E8)&^OoJGBV7A!pCfoVu)!2$;_SmIVX`n?)L#%yyjFyPB4q+}bg9Ek&HdfYh z1oK)u6l!5$7h{KC#@bDD9nIx7s-^A?~jChRd*PzMpvCX8+SR$=&I z-@p&qAs1aV{31+lVCAnt={BG1P%y-(Xq>1xRCg#?r=}~ju#biM(~0;cTdB({{uX{_ zX@2KweuQ7;Hf5YLQBiJljC0(f+%bBzW84_W4L7nnlug*>`aVOQl*UM-o~&(}mKG{e zrO-fuX0$Q1sLplQ|Ur2*TKl=(<9Ky zbiV5Xq(ObAAFseP9vh37K~m8^O%|KYWVa`o9F}BLsyQ8^*3aVX+g}=B8e|&WC)0AC zeVCLj{nR|)^c(p((@UmzOz)cZrtC}lv*~@)U!?<<4^1DN51T$$j+jrFzLUR~QbtX> zc;*%NJ^uL5Z@WA8;4gmr;*#gAwj}>W7hnDLo_EdtGyH+8uetN-U;pO6a}V@ey8Pb9 z&3#h)_8a5&O)Q!^<0mt(h(zbUuytsr&F)C()Q9Ve^x}dhw+l*5s4{=S{q%=*mr--}>V^ z+u$K1F1YxTk3ah&zH^sZ$+}?VXm4=h^q&-$%$jrcwb#$RsVp3=nBUNR$DJ!SJpG$z zx9|D&Z)$2^j@>lkHj8W?FIULYgq)VU&Xe6~nda=I^DSd7h33=?Tb{ONo3qWM?Y`uh zQ(6N_10D8^Nkw^b*q-DXXc;aKwMh9v^JSI^W``}wmamL5rzH91iIyQYbBe8GM!?(0 zYs;}aT1Q@W*;xC91BZ;v>^~@JCK4#@GuY;^PPdOrYD&KJ;tQ>lEDr0HR>_hsTUzce zKYzO2(X#2L5k<)kYai!CtHVFeJgDV&lOwZIrYAY377d+lpVeoE&Czmfs^dI)+Khml zYIj)kY>rm{VA~`)^J*#0)2Hpxil*e29V?2%ecD~=1MhqKu4(IkcUPY6Li1efNXJyi zXp8f%XK#pJX3n$q%_os~=!Cuf&le{B;^S6tnslBu)ogEFx!gS8(nn6RrT?sKT2kZW zmSc_vd)V zIx>?7rwr+no|=+oPM7;(pY1?tkU2vdEDx~_l`>7k1}gGcd36#owRInQ+P68%zJ$e$T!4|Lm#f zUi`0}yWV*7?}z>sXJ#(Yfr*nYn(>nx+wTQ&%ZvZD>&>^{IrJ~qCGL|*-fxOT+wXt$ zu{Yj+r%&H86DJkTxaNkrHA{gX6E^>5>+fHG=ly>?lK;>e*L}nOwD;}!%qy5I#-4XS_{+zq;!G(Wao0c0cNN-)nyr0XpGj@`rDa%B>ri>HT{2HF`^+|3vRQ3? z9VKb~Y;$a~In$9O+hv;!+euC_TjXS`lsdpN(>Bz04Q#SODJAA9GOQGHUu#;*MDuwU zlqw6%KfR!3x8<&9YpJtjTiA zGayZHUoN+7uuqoLQZtfT zULMhy((>maDVCPFrR5(fUp*!Vl3M5XZ`o#V`GdugF-dkyld9 zGBOquLQ#nQ4Vz4fR~QZBTDdXKr~WqGKa)`!Lx^hmc} z#iZLMX=sXxk2h$p!6n7xG`~v^`6Ii0@>TJ;nH=ztTRz@#2DjO8%Y++^zv-dhO1#-{ zTSE?osp%!H(lXO>`DYXt(U;*}3wk9P4~40Uk^Ur{56z0lSK*iFvqkurh1(0e;XHeG zJibArUz?z>rZG!4-p}yvg`Z3{4Oc|(=K+m`$GQH_00RBaHm0v~&?p z0p0*lC7?~m*o}BHw>wYxyzg%KX{?CHZ&$O9nw(HP&2W#v z@7db>8qlAqIdglbJZ%F#vo;>5H0Yr?-_qR9#PbZ$KLdR=!ZcC<- zMia8B0B3`iUWc@_dNIl$r9B;fSpAuKP4QQPz8&;p{H;%$!nT8U1hgF*P2ZL&>;}+R zH^k%nRk}-`@9m(?ZakevJlYRh|EBJBbOdf@xMfpZcoe+2N|gH}T}5(d)NPc9(eP8U z5VD8A;ioGP#Q#Fjz5$Kbg;vLu{#>{pfxBpXM6ZL}VYrb#M?8vXr?|$2HQ$nuJMz00 zZfoFnK=sRY4Do9V+{>CFw`zV*lk2?{*P`z7dKhjkIyZ{vB;1z4ZH*Scp6`@?rVanx z3SCU}>8g&Sa6Y)F!+jOGpP?_B4SEac)Q=F|C@&OuGyK%u7LS+VZ}{P5Bc82-`!={! zI`oj+2Doj98^o7CR3F>m_AK0l%m|sFxc7o~?d@8-*5W4j&*0t+_vsXi#(PS~jLzvv zxYw!qEiv*T8}t)*XmwMT$m?Xd_g|dQVU*VrxG8WGbxv*(xMk@4QU06ZmJPQ;jYp!r zk^j}872lbV1#){5Zq;xT@lw8Df?EV`XR1F6vmf;RpyP)>6y^xP9=PReZCP(e5Ir3e z21i;^FK3~%Iv!6~ z<5SLL8&aP4!e7}#@Q1(Yq2I%Bn+rFE9Pp65oP=8?+-8#l>RsrN(L_f>TL+q^V_lV} zmvIf)$@|?x_f5OCNDj8g@*~k{j`t9$tR973=&_ zeqEZI)>m}(Thrmb;mL%qrSNm%wgzr`Jy8d@WjZ&CvmI{DaLdQv;0M<;)@{G zpDtax1@3#`uE|T6`&)2Nf2vCkyZC(w?qzU~sC?jjrE;Ex`!i2>wf%G2)8nui#{8=; z{d8LUEC#(D^wFwbD2trlW_Y`6B!9n&$5*T6?b6c<@G8(wg0@o4Yl%@VsXc9hpU89Z z_--w{zP(W#dqGe6Z9Lw7mN=+xPQXufCv+3Vfrs2u@Xs>1alHskb)dj)72LG8-Nn-& z+z*_=y#(&AE#3W7e3fu-fjf->QOBz!U8X@|%ka-zFF+=Vj)&Jjxot!HQOnUKYg^zx z?nSLWRqy=Y$&V@gcf;fA?-mV@)8jei*aO?7gsZWeoHp>#{&B_a%W>uS$B!M0rFD~>F%)=o?zJJ@`rMRdAZ}=i?N{LUM#%01743iH^-eDV06kSoQNzZkelNgUqidk zvE6C3Coi|$pXZHKC<*9R*F7VX3;B?wUtPziyeHkB5z^*XjnTbiP3~<{g>e>Y@@2miB1}6Rz-h$tg z|Euu&C;WHdm7s&goX&OjrwQyqymS@`>XXNRD{wn7WscH&6`0QElxf(3`kbo^p9@T9 zkc9s`faxrdqWRwmOy`*DG~5TeF#EGa`a$4t5FgALp1&~g55UP9z8Bc8^Zz^G3}E5^ z5HOu9qV`YuokGefSz+`;xCMWhfhTMD6X1N{5|oSRmtp+09sE)s6Pp8E4Z8YB>?Yv! zPZju8^M`9WSbt!_&n>_!b^iYwI2&}Q=KnBoQ0JfSB6>#WAD_iz({=u*0l%fAmjGAm z=(hpWSv>WT80MqdouJeD6V>-`fL8;H{QVV}&g}{R2Z1+$PHQ*hKNVw$Y#n_N@XMeJ z{$2{4ucKcE{5t3)&lG+kFr5WdABo)w{5Q~%45vR0deTw0v`tE z`U>ImuS5DM5ACC(@TI_OMfreFUC+ACV-bCDvWOk+7V+m9@H7LS102avv_KLI0axqr z0^nzm9+i*ybp+*Ghx%wHY_hV)4DtOp@U!qQ+WW`AbOwr2p!&*70slcCtHl=vp8Z9l zzHoIHivW+-=v#qT>gXQ=uLTz2Q~JOb)X@XLALwv7usFX(`G5Bs#E<+?A58W0KKQvs z$IokTfZYeWOQR>>$hyw8k$C*EWaESpgFyIviyxD+v81RP% ze9C}_Qb(@KPtbtp7;v2d-)+Fp81QZbK4ie$u+ycV*fbRM68E}aKR~zs$1Kwc3+YNZX0iQ77!DLuy54Der4LEGT?FPKjfL}A< z4-GhOz~|9MC0+WH4EQ<&zQurJz;tGj>l^ep^bl4biTw$5I_IgUi*ujU!}ZI+ycpxO!bkNcd&|A z!9n=f)5#y5X;mMI-4FkSH^4#o*VD-#oqtsyiP>Su5~ej^;a^WDfBdX04FIIM=?tzuJ;LgPJDN~Y;yfw! z@AUN7(LtHXDPqJS>1)lzuS{{+#L-WZuJ!*VLoV`HdR6#f5RW;q|Mtrii zJKcyU-`t(9#{{g4nGWhtqxPZ zwk=fD>}mC<$2;JE4g3p!eF048$@TJ1SbZ=a!k^--Ht}~6usADDcmuFFGfwy&U~zVw z@OQu`P+v2d%I^z?!#+a!+!`(c7H6l)|82nHOf=z5z-7p9uIB$;3J*L%!*4{OPa&`Q z650ps;je*79%)|%;q#&xzd;@ao(4?vCj6g7eBz=0C1V6*`Dh>1z9p`efpz>CSIOAT zqWzdGtQDB(Xr?^98xUSR6d(OfXQ|Z(nZiToq}Auln9f)0>2waeCrsy#^>jLu-4l)& z=yczJ-oGB-g7Rb>P3Ws%09SvLke@#SZva;LWnw3QpV85?vQWP|OzF_w2I`}h--zj~ zxt^}aGZA0@akW1o`FI!jkPcsy4Sj(0(Cwi9OzbXTaW0(juYkq*Zo(e`i!C ziu^7Ert`X~TKt{Bbar>3hW`#s=XgbYNuwD*(<}1p1E#aRqCBO*bk0}MR{+zQUxA+o zrt`mpwD=DI(^+55Q<*ZwQ#q3XA-%1g3MtBK%fhIzue#>z}}Mp4h3S z*XKgU&lZdP1cB+CvA|(qI&&=ec`q=XKNj@g0n=Gzix%G@U^5 zqxrw(7R-mCeJdLN82AA6B|S7g-O#LJWRK%Rz`oDa_=ujp2<-{}dH(<$0iLX*Zv_5E zNB;=ejP_>J;v01S0+ap~{QHLir;SBG?GgH$?j2DdRbSEh za)HOf|C$pCdxE>)nV??{I-ODH^@kQr4`KCDvC;#60^ye-e$ik55tz=n>+N;I`uMiD zB=C3$7U5O!Anap3ox+v0D)fU#Vtaqe80AOsZ+AW90p%6)_bo8-!w28QUw;e!fPcZy zds@5WuMN2DuI}`^N$|CY_`TVHUo&9xs?RUsNUMT>>5=%qCtDT%dp1mW=cteB--zj6 z9YOyG(r^AYpBE`lF919jnCg@085L^!2Y{(QP0&~CK+hmL z+RIqf_sLd;HEQ%SVB%N4hVLVJ0H$?83O{zST0i|Y`aaZmq&1Mj$%F*@$H8L zmG5O>@-Oh`&_|U14voIpkiSQOOLX>R{XC4f1U8x38&%*h%FE>k{7ymp+XhSz@qZ@p z31BJ-;roFnf0xkDMN81%fUaotWx(RT1@iy7AwP}@u-{NVGyDsEpfB$X(COZTY#p7j z`l$R|eGdH1^6vii_;-lE68RVH0++L%WN3@3{kmq{TKjj4H6j^jB^aIkPhw5wCG8J?F0B=Y9;t}$$ z&kxb)t`GH5>xb^7=n2!kAbPqU??-yd_uc!mLpuLf4`X&6-383<)!H}s!yjPvQ8C?z z(Gy;0pl?41F1fFJd`28um7rhJpw^!c8KC<312E;E9^!ZX?XW+9dHn-7Kz~vCt3W6J z9|IFVX`dD0A$Oub1V2cB627+u?Hl=_y`+Tw?XU+BezZn^8kp+mfQJ7DO#Bw%e@Xn) z9;)Bhfv*+%fwxlVKV5mq>y94q-U^j2;`c%R8WA7W1j*Y_ua+2oggl8mJ>Y{A4;kX8 zdp^`hrR#A3@ofSBlHq~mpPmCc|K*^!Abm5ZTiD&eqkpC_+MguaD`EAK*z2Hwa5B+< zeg%9&htESrDnBIX6mCsSQG;vwH{xvuI^9jCJ`$Ub_{1F_l>Y``aTf^T$AQJ&AB5ik z7I%FR{>f}LeK_;_pHl_-0RMJq*fAgDJMd>JFv;8Hz;;m{;8nmu9exjZF8qu3KcE`= z0GJ*Me+}>k;B*adg1%TLg<-n^&eBkdRz!!r)TBGj=ZV~bb|L5PAxT}T2-;ex=N0eWmU!twj<)83c1NJ?r zkTV{YKSn&+K)-#B!hH+>M!f%#?sOv-`?N%OJ^mHSvjgSj@&oy&N9^Mg{*74d?-Fz) z7W=^j-H0=Pp2+V9NMGDzL+x)r>?tZ=8M4Cb7xhj26!jTJf1G|QA@7@kiN9-*Z}Q*K zfc6IL({P_g*w5gPi0^S=Du1&^{{!qR%Add)=)bAF0v9ibf7D05mY=o2R9->f0r?Pj z=a78JenhN2LO%56CDKY=`Ok#S>lAXvgZ%@Qu=nA=4v5M(5c-J1i}Z&X(z_Ix!qdKU zp^x?PQLL`@3jN?w4e>o~zlFfcR6On%3P*%LLHPLyKbBKXY(O5; z)0HnDc!v&Cz`45c^FbH)9#Q%a0*i9=gNqC$H)M!iIP059cK4dmUzY z+P8I&&xqF==p`?9_iw~yI{L*(uN~4qu09g`+Zv2lbm=J%L*D?? zL+OPzOp-&m!w}yufDZ`&C=Wf~=;D71^h2Oi{)B$4{x5~R;ZfzWMTd{W|2Oc@%ZK`Gwq zQ2o>xFwy8PAN5iBmHGPwz8n72QGT+ADE=3KGl4~UD4h8fg?{iztl$wfK4A}ic!u=! z{wdUkR~7ofqo!}f+YIzWI(!Q9O7X2jP?E=`NT2QmfxX6VdCu>`K3qP%Ov>Mtn>eG_!svvQT+|dSFygmY}5JY5$;s@55-pi z|A#DMJ=?_Q1AnH&W) z-|0>_;sblS(~X$!HdG(A{CfNl__a>QPx3cT=l@mEKLcG~U#oTWe}jI~KtHLYXIu*V z9``?q@Kb=rJz!M73xLI4UxXh57Wa1%eic~U%|-a%z~as>!WmOApN;hUA>V|j0E>IH z2-g6MyRryB3@q-iF<#Z-9pI06NFRL#`yhNo8}Fd}z8LHS)ThYLLg2Zg zenD@7zOB>YDTrU(KSuof&=CJA;CA>Y{!@L7E<}F`Ob=mtB7ai&FS*dOXRpG4&xQ~E zIYGY)@rirQD8Bu$Cn!ETheq{%JLuw}@;+?9MAOIjf|ftgzkdk4Uz8W|rxc;R=rDz! z`+-6~c+~tG@%FzcoJ#Zn!i)RSD8C)xAEhtON9+aut7AATq1eFBLF*X1FnKr|hNuZ& z4?H7fIGdp1$AC{FKi6vh4*<`$59jlT^er}6!Inoyo@#7u?-e$lD4LEhG z2#tOh;qweQV!-zq@QVigF9S}W);<1723%pl_Z#p_2K=!B_nY25{)-H_(tu+I{IUW6 zuL1X;(LMf44EU!8{D1*(H{eeVc;HXE$6sK;)du{K0l#X%|2E)^%eu!u#ei!J_+bOy zVZdJ)@Q~u}@fR6zodG{;z`G3iO9RflynFo947lEa9|K;MqOjFyPyNt7e*t`ZhQhWX z8p2Nl2m7l12jLfiT{^rI*bF>Q^ZyQTzK;GE;KS*vex>lA0G|L((fpqTu1-_f?OOVd znVA2(S>f%U{7(bkeSQKz1H5OL!tdK6`VCj846$?6bbi!fpeu(&2lqhJCR^;p-g~|BJw6Kj&-leF{8!!f+t; z^Vmf+?i%n%QP?w=sQI}Oc*9`y?-mt50?c+M^1JRj^dFrGoN+z)^NxZsoa+B7V6x|2 z2uA7O16;g5k)K__TYwdfe#s5!-yom#q{IJI;C#QxpPBs*SYN-HbGz5??ZEo_-49Ij zF?8nyr60Z#>zBxXM9bgL38TI#MWVlQ6WYgSln4DQ;lsdWFA8~ksto=8Hg$f0=wAZU zd=1#n{a+YD`QF6(hZcSwFxk_qHTp(i8o&3~@CU#&|3r6eP<(yMQUA!FNUs=}>`{U5 z0jBYyXpcvL_3~X3?q2?9f%Wp-C(^yVKLw`!_jH#VrT;i^2IL_f`RfaLm{tLKfjoiC zJ`?a`Tq;BxdHZzhD+;UZvoTY zXq5h=z%)KTti@M!Gs?RV`a|QjV%?hJC$cR1>0cpNW z@b7tG8o$u}1VsN5n8qu+webJl0{!)>!q;DkZf{lXA0aQBJJ6odzI~eiO-rGlmMd(# zhC|CxpX)JSs^R}#j`j=w*@63li@#cd`R4nf4>bBeS9Y(@Y4>!m&!>R(@?3Tw>f^-( zKdh@%dy@7SQGN^V@2;Od1lH@PZ878r@|~%rzZLc_&BxI_A{73w52@o#n(rli=^E^x zd?TUXHa*N3%{S2ffMLj+m#Bv%`hlcWo2A0GB z!S_w+J3{bGcLwC(6HxV4xKcR^dc&dxxP2GDmAGSF{Y(923-C>l1)=KF`ezhTtw)K2Hc+VfG^MEFV72BxcqrxSDrWOD-T9;0=@R> z>$OjJuYKnB+Gidy!RIN>E}os8ebvILrzX%w7h9v_O#jA zUO;fh8wo{xp}YVX>I&vnc#3{xJOMX8&fqPNM)3ItUm#fiW8;YgJdtqJ6DrRu&yC`{ z4ZW`^ckYkOdZfG}&lhlqarH$mz9td*v00DOog8_-a(ufY>JNGSKQ^8Uw>yGwYxv9Y z$%;sBAlQ2rc!Ir_7fA5=|0CFTOUCtBP;cg1YK6i!F&XE-L3l z{y7$%AP3!{P(|1iap&enE8HP)jT!`xzOJ#}c@$4$+5yDVy{n zB~L|#FX-{)x}$*rTArFse}K2!Ge$Z)drEczkDzxAx*`&;aC<}1Tz?ebNQv?W^pn{$ z+^$j=>gLi*@kj6VkDJ2uPEookRvx{l_hJ46uU-*7{n5)Tk&N>!^JS z^IYDrw>;pf@Z$UMo>0QN>C$6f?`f)tdi(6+67>3bRV5SgMxxPjcX`O;Eq8^=LtQ;c zAYAT`u&1z50pwL6Q5Q_|msu{oI&40Ebep z((rH9yqahvNHtPga>XpvN*KMaH<}v>_+f(iBY`5-jQdZbbLa7o@05mXt0Sf28y<){ z&xg8>RNzxndBJj**W3HjC#3nDrBC#q=l0sAZ_n-3dk$%EpM&mU3z{0LOHl>*W@=8j z3x(?z0p%3eh3li$rIl6G!o=V1ZuRIRQOuh)8=p2VoqYv0pb8HRq<{xqB#iDrxT5GB zdFX2AE_ACN1PHo3s0)~N!AQX836y)I6)tyf$gfs;mu&k2r^&X~BhqKoa;}bsdAIHL z=(}^M}>mj%%)Srrjmz=k(d7bD-h1px@inxO3SP8k-Wy7 zNXQlRz}mi}I z=6LYc&Wc4E0$f!0%Aa(f8p?|~NRffnq6mUngy^EFop^EG^y)_CzsX@($r{0z!Qpu-L7DT7bdDpBsDKeU#E`LF35?x{E?71 zTAmjTVbtQ$6gq2YDsQZg=7fTNe5%&tcX`Xbu8>FV99=9_v#7H6mK@9mMqIhUa(5)` z3Ay}ggX@{+b%2KDMto4CMPGv{m_of0Z;MVTN;+=iu6i0J zwHJ6pyQ1Z`WuB5GcEob}Ojt#WgLYFY+m*>#JB^2H@UE+N&Wfuhw3-fR24!CPa!5D@28yd-g}`cUoR=mPc)1;g>C!S+|)Y z6rkE4cM$xvGe>kkYm6THPV2l*H6HaJ_tAQ|dDwj9v8HbESS1>jq&4NB_8x23)2Wf_ z)2>!&R?3y&!`8KDR7DV=?MJLZkxK<@1 zNEViJVttR$O0%vX3=(JgakctBLsUGJ&Cl)s+MCtpVcqk-lRtD4N$5FnvZBRrr}{Q) z8MNqjPQH&|JMkkwt)1!DFWzB`Ee^pto@j&J!M`_xo;`WPe_SQQWY&MEZ zbgl7|w)Oc18?cR;g^Nzk<8aZ*6%{Tzd6EQtJdlAu-+p+%eE#g)_aENA zD3?pr_Un7ST>kRK-yw1E0n|laH92}aaaW=NvT){g+$l_0R^`z3DD)hJsziBD8g0-Y z@#&bZONYgFM8id=c?uVu_Ds0wBibs1zxjO4<>U)@)iol$aIyAj6CH)D=e5y8_(+X< zSfnb?@CXC2L7v~-5XsWDE*R^w02ES-vrLxCe{>UwuZ?mbJiOC32p65ULAdC2@P>;{ zk|5IB+nz~L43@pNNd0m3F zAW*eH4c&EnJ=urmS5WY|R=aUfvf$(@`X3 z*Am{D4^%LFJ8_++-R^(0_Sd}OgE6aQW~P~=bkrBCIP%;;8e-`s!xdIj>L+Os zY)?K(`Eb!mbqp7sPNZ)xf8hn|tcZfA#V;UvJRq z3YJjTl>-W8D_=jo%BSJzG~%rVev>FJq8)I*CcP=jx-Hrkgl50c(;$b70s%RtKLHbP zo5(b)_5DJZBz*v2ZaT6&h=zKg03(+A&1TD4U~86%S9u9Ic4_|zQg*X3-}Q8w5EQ`F zRFTEgYa=*udtL6b>pyV?FJXQ>h*eb)7EAI9%&9{OWKpHks8WCeZf;iXVi3G-o9iO& zD=-Bk9O2A|00vHf6GXu252wikKOx|qENT0`?^<%=GR6Y+q|BPWEzM$D%E6M;1`U?f z=bGm7xklATA0yvgl-_l2abv!$9thUIvadGv#zxHrYChzuBNe9a@dURns9Cr}KUl@l z`97OP2Nn$vahKK=FligN9*v`{2OCm?h%y~@`p)}T7O&;@mPQglsCFM;t9r{2F*G#MKTOP>5&dD3K1+?oqJ???!&X+tj~NC!|QZ6cLf?wix~^bos{0X zb?Vpk?LhebTd{Os+P5P2*0&_>TNLN|L10yj#p~6M9gGmfU4V=m%uuNuwQy?#6ROQ~ zMYd6jd8G<6S#_RgDr*hdLO`;%q9j;y+VjDZ+xZPWeLKCOl3N=$`1tKM4i>d}pl*GI z8nA_*1Z&+2-Eh%qZw8C*#G^uO-H99pi%ya>*npiFPpH;Ojs+{73Aj_Y06u`%YSW|^k9eJtcpd}RJkBVT?t$+v@oupo{D6#|> zz}+?O-DUG|eRF?(yIDvBmH2&nqDFa{IYSx&5nWVN#>iUbkc%sd=QFx!e7CGh5Z8bt zzFSHbNMx-FlB#2Y2T zF`q*=lRouGt|>L}5Sp9T5J6>wAs0WZ@#fo*xAj~WF260!8P>JATMhnRDNL7e(lahqb6tIsQp1p3IdBTUgyYLgzs;GKE z*h$mqq#c?4q@BXIwsl!U=wN;2_YZeB{c^bOZ@QG1+iRPe1!$g}ID?A|FLW#6=iQOm z*0Ps9NGP9K*F)D}P%3q5j?$Au_|@DTRpQ|Hw1vGU4xP3`p^~O(h2dzoSphP+`3c&s z-l$fayi|SHX9>A*kE(utcJ``I$|8qyF;@vZ1&QC2iHD)=38I~Kb%?!h8&;+w89%F< zY)E#t>A?gSZi30|#3ScsINQ#!>PUGe%1dOkPuk2Ss?O1ARu>u0Y%ym+_#=GnV%Uc9A(GOH7)Z@WPe(HwfG ze<j22xSwINUe#3ly)UzxSqx42`HhpflUVW1=PG_LvMZ3< zcJ_jlW8-sc02R8-XnK)>NP?ev@0hQ|b4gn0rnX1pD;}!B;I6;$XaeXk3>K{*2{Yhq z+kGjAzmNJQHG9 z!ro9SW?2K-om&g;i~b<19HiDCEY4OyhCo=@X*EDV4gW|s4pVS?&djg3%}9o{2kP=} zWn*(cx8wKtZ3ud>tr-h&guq*h!OKb&n4n1;KSXOtxYhGf&uMy&;?JvkDT-vDYse6U zekcJmvAg!Hs+XTsBdArn=XJfk`oXxus?h7EV{)N6 z*l+(K3Z@Ltcrd`uRc#Myst-`zV;GW3W!F;wQ>lSh>kk$aQog6$j zQ#*pZHk%C=sy78O>TZFwu#dISHnK|Fsxn1=V61Gr;Ee!x(3LfWfv|8T22O8S7k2vn z1bv}`n$e^-=?LpSbj|}s2gL~@XlQ}o>n-KGcR33A&M5Rqyvp$?m4N>rA`b=XZt0?-?iMlklWg?gUYJ`asn7U zpuzA?q-niuca(5~2$0R$ZnD2KI88vHkZ)ab)*RU5)47(W_DFnZO+M|6daSk{xQcGd z90E7sS-V?u_fXvX^7dRLv5cD$$X2Rg3MM;gXG7Dx)VqW1p*A{!44EHf&Kud7fWi+R zxZBM=*c=!U(N^jj-Xy4D@@ih~teo1}0HyDMG=J>d?-?OjkCPh52b0H1UU~gkW@B%U zWp0l-zZH&40-@pnqXGkZP0|pcVNP{k9jFc$o@v*6XM)xRkf9!}vBd?DADjt+GiUZp z+piy97})rF@czBV>-V_&XV0|#`g>9mD%zcp#FTcub6{x4V!yNQCs^c(ePR8sqR{Sn zk7|PjQ^Pb|cbuIbulw}M-KkW!73K`+c8yL`l+F)+)bQ_A19F7RChT55&~fXx=JQ|omULMx4|@qgDo*2m z{c9YBtM&5E(Klg3)D7xJqDcoc8TeYna71Nf&)K@Nv|Dk{i>p_-X`PnL$alctRS$&| z?i0|&+d&cARF2+2Hiv}^9J?@Bee|215WZ(!G#c!O7GBUK=3RW!CU7$f%sHJiDR zNm}$oeb(?1XLHG#GO|{xA?VB|FW&g!lzH)TB6gn8=+gfEQE|(mDpz~MCxXPN~ z<$9IY`I~*XkO_Vix0RkCnqe%9 zx+#k)tKmc?b&auf>cWXy-Nvx#qiOMMy}!R4FQP0X>cu3fGpu=R0g@+`lRNQW*Q|-0 z)Gt%DSkbwgVyj~S&cC@)!t0urZ}|Unew~In)v{vP-N-4_Pwr33NvycJhQNO*kvrSr zy2ZfI!ih6LzB%eg5bR{gN7!X6;8}`U5;jV?W{FIIDg%N~W)S|QoREaVca1Kg+oCFp zMK&sRbL%Cp3U3YLj6Pm*aWzaT@)N4?ey7=1u%r&$h)9NAgNvbsUAri9wlx|PS^~1v zwmq0WmMX8Ko}7bl6{Cglget~qyu6C+$^94?!sTr^HT6#%MMMgjsXI)u~6|A<$)2`^|K=z4(`VK}^@y2oWM~c?dNJB`|B>CAct#B%y zUl$1Ylp9LO^3eFMldJ~0J1*%Qd+T?^qw3bjiN@G-V0~Y$IDRluu5=~8fis7uJ^lYi9f7G#Uw40AgUGgPBr|U zB;4-~1-7702As*lxR8q<+Mn)Q1wKnGro>s4aHV}5bDE2R{YoU;U`lbtnA53C=W*Pd z3-{H7oQM;K&lum{Is~vv(v~en#%D_kA*!q0oM9r1QD`TG!f^^=(%>jZXUO3L*>-6R zep<-R80U2A=%h-gm4b6R}dBPA|(62Yd*vMvX5dMjtckNVcJ4vtDzaG6?0XR?Ic zb34|*1#U;%HkLL1^$c?ZS(eoV9cP*|L+hKh9d{g({|7mJhDtsyfT{D|j&S;o#A)k- z$d}16ZHlcGHx)lIRyk%D+@{3jQzBn_N97V{_Kd}1`V@XjZu%o?mzITd2-HTSFoL<$g-vq9FZR=5@Il zGD9yuA}kmz4xD4FFUwz>n+GwxGPzq+VbQ09A!FUGt;zFeT|W*+aR44;{fxJF%4skn zm-hWKX`Zl{x(?F=H+?%s)8~8O9?HRub#}xHBg&1BP3{BFx-Yj@s5#kZy?y?sL;l?S z-2M5JS$}UMm>iOGe}+0|jAP1{22uv_q(Wd6tePezg5nXbA7*nsmuDBWkP+(4o?l>EC>a}{R`#n z=&U$q1+}svyc5s0cRY&hQmoEI8tu)uyL)FEV84pj{oNXr4}sn9Zomj3y1W8!6JB0HesTdtj)B** zE^mPkon2mmw@ELr;K}RYsS7zhy^=Xk5B$ZcgJUeeTU%Ec4sB4(kY=FYLXQA1k&VcK zQby|~f}(IX!SJsfmH2d=?nIafQ%E4qqFj;E6?X;*=M?u=6D3htM|LFy)s%E}@SM<7 zrbll>afua=?*(2vMdAR)cDiT*S(}Vt!GRVq``v9Iu4_`G!JTD<5HfC^j+I2Y$JNZN zAtvB=&IrvjFSxKAzA(@fTt=yJD|1VRRpl?Jr^Zqzb)WDR?n=l?Y&|1_b;RYLJ$c_- z73Rn^w~CtmqI`Z3+3LAkzN>W8Dz2i~y`y?E4-UvK+nx)M-~hq5&%LebPBim`MbVZ+ z&*H8!B2j=U$Auj{WAoEuUM5QPI&t#A|8+xf)n^;e!Xq0oX51F zHp>8tet3A7&`D{&*V1FMLkpF$Kx}G-;f(w44PY6pLPX2fi4A#`;N*x{5Lu}esZ`V} zYKG|h4xG8#6fVbwinv&)X*zEEQ*}OYHK1FOGGHY%ka8nHuYUD+N5~V!C9fTg zBT0amq(@0iiiAFK%sRZuVqtM6_|yryY&I{}>(!`q8ZynutCM3LF-XW@(p-))4oq6% zQaGCT4rb7cd z9;vuSj7R+CHKe0Ve?k?brGI%9*}0CeXeK3K0+l{4ZTWh0{SWqTP`_@t3b#hW=-E0guoN#fu#q107%9|u#eHJVSGY0uxqC5 z$^Ibo6a0MB54dd%_*Sx-L0okSK-4XQh|F5BXbB+@uAd?f3TK5EsvZ%i-hK1t!>g~x z8^aLn5Nme@c_2dX3qdvldQ^31DvN7QKH^v|uVK`cFRx)-els;NB&CZpxrmJi6o@#y zzXq|jc;(+kAJRQw<^iVLKFKp^i-D!skqX00d_PYhI@}(?*3%BMslbZbclILO4YNo7 zCaM7|AI}PK`cXRwk`Mbi&I^vUjEl@j11gH5$|2*hEe}@UhxcR!WT2JYhz@-+0o68b zOSF2$b)7{GfTlxOkH8w>UgVAuI47h{A`4kgt_8sg{32sB9#wECUi9h6$ULBYH({My zXf=}yh9*f`E|c+d8*JaCIzFj=^KxUiecT~XcPSjpk`voYI)$CVVEZQh@J#zKxn`6I zw`-7jXu3WNQQ$b;c$)x+xd@g53yS<^Nb3MGgN*h{ga(U*=b2kjkzaVAs&U3ar}7t4 zp;ZQoTTlyz{Qf@W0zwd%N-ptnRVb33Fr11E_%?D5JeFJ<&c+SaFe=4QsKHO`Tn#Kc zy-TfaN9fu5yN6FWg*MT`1ml-$)+<9M4sIild3T~p}}p(6~GyxWk2R5p;r8d&sf90P?Bru2P{aEJe~z7CoM?vn2)iSQ*8*>Fvd63Kw4=f9oj97JSDeuIGlaFQmqyzO?}{U;(aWPEZ!lesLcN&w-Wh8l9RsjxT;a{FL8(WX}1H!+%G0<{&Xr8B|QLHbfx{(K8nF>;UqK)tkzd{jf{ zs+g1v^s}_~S*v11+g!TkT42YTlpH*B72Fd5>N1CjE&V1TNP;i_4rlh7OE!4_R$e3* z;br%O^-0bzfp~D01$1Y69N#d@Z7ZUV@T>;omX-hmX~X&hNY?! zmEd=!FQN&!nGV-5=>^9%jI$IOj!H`mq_^*vZ@&Ke-HZ3jw;x`=V;TXdcKDhG;)?@5 zkEGqFR$Ur$N6aEUak;~!sQ7ycGCQ@7tj+rGM+3?sA4?7=c>4h{`m2Y| z`_2FT>D6!k?ds~E|I~lT%YXH6|Abd5_n-Lp!yoWBY#b@eafhx~1<@4x$UzsKue zE`E0Pmw)_|t3TuY_%oLKDSx0zS5odHle|)+BWj}HM8_WGU zze@WO|C!YHzx{i8k-h6$l>7I;xVrj7 t{_u}fApMZ;zviFxVf^`nH$S=hpW`pQj`jU5?{~|6q}=dN+k#`c{|^!z(<1-? literal 0 HcmV?d00001 diff --git a/testing/zkvm/src/main.rs b/testing/zkvm/src/main.rs new file mode 100644 index 000000000000..8bcb12df9d0c --- /dev/null +++ b/testing/zkvm/src/main.rs @@ -0,0 +1,22 @@ +//! A simple program to be proven inside the zkVM. + +#![no_main] +sp1_zkvm::entrypoint!(main); + +pub fn main() { + // NOTE: values of n larger than 186 will overflow the u128 type, + // resulting in output that doesn't match fibonacci sequence. + // However, the resulting proof will still be valid! + let n = sp1_zkvm::io::read::(); + let mut a: u128 = 0; + let mut b: u128 = 1; + let mut sum: u128; + for _ in 1..n { + sum = a + b; + a = b; + b = sum; + } + + sp1_zkvm::io::commit(&a); + sp1_zkvm::io::commit(&b); +} From a151fe40ed04dd1467aa576c71170168889c7660 Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Sun, 12 May 2024 23:44:14 -0700 Subject: [PATCH 02/30] install --- testing/zkvm/install.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 testing/zkvm/install.sh diff --git a/testing/zkvm/install.sh b/testing/zkvm/install.sh new file mode 100644 index 000000000000..d297735eb6a0 --- /dev/null +++ b/testing/zkvm/install.sh @@ -0,0 +1,31 @@ +# From Raiko +# https://github.com/taikoxyz/raiko/blob/6a8421d5c17a7d8846c22f8f986d9584a6885bf1/script/install.sh + +#!/usr/bin/env bash + +# Any error will result in failure +set -e + +# Check if the RISC-V GCC prebuilt binary archive already exists +if [ -f /tmp/riscv32-unknown-elf.gcc-13.2.0.tar.gz ]; then + echo "riscv-gcc-prebuilt existed, please check the file manually" +else + # Download the file using wget + wget -O /tmp/riscv32-unknown-elf.gcc-13.2.0.tar.gz https://github.com/stnolting/riscv-gcc-prebuilt/releases/download/rv32i-131023/riscv32-unknown-elf.gcc-13.2.0.tar.gz + # Check if wget succeeded + if [ $? -ne 0 ]; then + echo "Failed to download riscv-gcc-prebuilt" + exit 1 + fi + # Create the directory if it doesn't exist + if [ ! -d /opt/riscv ]; then + mkdir /opt/riscv + fi + # Extract the downloaded archive + tar -xzf /tmp/riscv32-unknown-elf.gcc-13.2.0.tar.gz -C /opt/riscv/ + # Check if tar succeeded + if [ $? -ne 0 ]; then + echo "Failed to extract riscv-gcc-prebuilt" + exit 1 + fi +fi From 474cde07921d55cc24421f206f62434245db9750 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Mon, 13 May 2024 23:50:31 +0000 Subject: [PATCH 03/30] compiles omg --- Cargo.lock | 37 ++++++++++++++++++------------------- Cargo.toml | 3 +++ testing/zkvm/Cargo.toml | 2 +- testing/zkvm/compile.sh | 13 +++++++++++-- 4 files changed, 33 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7efe43533cf7..8852ca37fa28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -146,7 +146,7 @@ dependencies = [ [[package]] name = "alloy-consensus" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" +source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" dependencies = [ "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", "alloy-primitives", @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "alloy-eips" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" +source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -222,7 +222,7 @@ dependencies = [ [[package]] name = "alloy-genesis" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" +source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" dependencies = [ "alloy-primitives", "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", @@ -408,7 +408,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" +source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" dependencies = [ "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy)", "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", @@ -490,7 +490,7 @@ dependencies = [ [[package]] name = "alloy-serde" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" +source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" dependencies = [ "alloy-primitives", "serde", @@ -897,9 +897,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" +checksum = "9f2776ead772134d55b62dd45e59a79e21612d85d0af729b8b7d3967d601a62a" dependencies = [ "concurrent-queue", "event-listener 5.3.0", @@ -1248,7 +1248,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" dependencies = [ - "async-channel 2.2.1", + "async-channel 2.3.0", "async-lock", "async-task", "futures-io", @@ -1493,8 +1493,7 @@ dependencies = [ [[package]] name = "c-kzg" version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" +source = "git+https://github.com/sp1-patches/c-kzg-4844?branch=uma/remove-taiko#ba2780307b218dd36851a22708f722b03b2f23a1" dependencies = [ "blst", "cc", @@ -3080,9 +3079,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "findshlibs" @@ -3495,9 +3494,9 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692eaaf7f7607518dd3cef090f1474b61edc5301d8012f09579920df68b725ee" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" dependencies = [ "hashbrown 0.14.5", ] @@ -5702,9 +5701,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "464db0c665917b13ebb5d453ccdec4add5658ee1adc7affc7677615356a8afaf" dependencies = [ "atomic-waker", "fastrand 2.1.0", @@ -8316,7 +8315,7 @@ dependencies = [ "bitflags 2.5.0", "fallible-iterator", "fallible-streaming-iterator", - "hashlink 0.9.0", + "hashlink 0.9.1", "libsqlite3-sys", "smallvec", ] @@ -10217,9 +10216,9 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" [[package]] name = "walkdir" diff --git a/Cargo.toml b/Cargo.toml index 2fb6c54b268c..1faaebd503d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -402,3 +402,6 @@ proptest-derive = "0.4" serial_test = "3" similar-asserts = "1.5.0" test-fuzz = "5" + +[patch.crates-io] +c-kzg = { git = "https://github.com/sp1-patches/c-kzg-4844", branch = "uma/remove-taiko" } \ No newline at end of file diff --git a/testing/zkvm/Cargo.toml b/testing/zkvm/Cargo.toml index 0f0c81c49494..e7ff9c0115f1 100644 --- a/testing/zkvm/Cargo.toml +++ b/testing/zkvm/Cargo.toml @@ -13,4 +13,4 @@ workspace = true [dependencies] sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git" } -reth-primitives.workspace = true +reth-primitives = { path = "../../crates/primitives", default_features = false} diff --git a/testing/zkvm/compile.sh b/testing/zkvm/compile.sh index 703117f3a986..fd1488c330d1 100644 --- a/testing/zkvm/compile.sh +++ b/testing/zkvm/compile.sh @@ -28,12 +28,21 @@ # cmd.env(format!("CC_{}", self.target), c_flags.join(" ")); # } -export PATH="$HOME/riscv/bin:$PATH" +export PATH="/opt/riscv/bin:$PATH" export RUSTUP_TOOLCHAIN="succinct" export RUSTFLAGS="-C passes=loweratomic -C link-arg=-Ttext=0x00200800 -C panic=abort" export CARGO_BUILD_TARGET="riscv32im-succinct-zkvm-elf" export CC="gcc" -export CC_riscv32im_succinct_zkvm_elf="$HOME/riscv/bin/riscv32-unknown-elf-gcc -mstrict-align" +export CC_riscv32im_succinct_zkvm_elf="/opt/riscv/bin/riscv32-unknown-elf-gcc -mstrict-align" cargo build --release --ignore-rust-version + +# export PATH="$HOME/riscv/bin:$PATH" +# export RUSTUP_TOOLCHAIN="succinct" +# export RUSTFLAGS="-C passes=loweratomic -C link-arg=-Ttext=0x00200800 -C panic=abort" +# export CARGO_BUILD_TARGET="riscv32im-succinct-zkvm-elf" +# export CC="gcc" +# export CC_riscv32im_succinct_zkvm_elf="$HOME/riscv/bin/riscv32-unknown-elf-gcc -mstrict-align" +# cargo build --release --ignore-rust-version + # https://github.com/taikoxyz/raiko/blob/6a8421d5c17a7d8846c22f8f986d9584a6885bf1/script/install.sh#L4 \ No newline at end of file From 8d26f24e1475a122c175551eac84f694dbe33155 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 14 May 2024 00:28:02 +0000 Subject: [PATCH 04/30] Made interfaces compiled --- Cargo.lock | 2 + crates/consensus/consensus/Cargo.toml | 3 +- crates/interfaces/Cargo.toml | 18 +++++--- .../interfaces/src/blockchain_tree/error.rs | 2 +- crates/interfaces/src/error.rs | 9 ++-- crates/interfaces/src/lib.rs | 1 + testing/zkvm/Cargo.toml | 4 +- testing/zkvm/compile.sh | 43 +------------------ 8 files changed, 26 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8852ca37fa28..961f7ea24e42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10750,6 +10750,8 @@ dependencies = [ name = "zkvm-test" version = "0.2.0-beta.7" dependencies = [ + "reth-consensus", + "reth-interfaces", "reth-primitives", "sp1-zkvm", ] diff --git a/crates/consensus/consensus/Cargo.toml b/crates/consensus/consensus/Cargo.toml index 308a16f2026e..2ed55e8041fe 100644 --- a/crates/consensus/consensus/Cargo.toml +++ b/crates/consensus/consensus/Cargo.toml @@ -11,7 +11,8 @@ repository.workspace = true workspace = true [dependencies] -reth-primitives.workspace = true +# reth-primitives.workspace = true +reth-primitives = { path = "../../primitives", default-features = false } # misc auto_impl.workspace = true diff --git a/crates/interfaces/Cargo.toml b/crates/interfaces/Cargo.toml index c2e276a3359e..2d63dd1ba7b1 100644 --- a/crates/interfaces/Cargo.toml +++ b/crates/interfaces/Cargo.toml @@ -11,15 +11,17 @@ repository.workspace = true workspace = true [dependencies] -reth-primitives.workspace = true -reth-network-api.workspace = true -reth-eth-wire-types.workspace = true reth-consensus.workspace = true -reth-network-types.workspace = true + +# Used for p2p feature +reth-primitives = { path = "../primitives", default-features = false } +reth-network-types = { path = "../net/types", optional = true } +reth-network-api = { path = "../net/network-api", optional = true } +reth-eth-wire-types = { path = "../net/eth-wire-types", optional = true } # async -futures.workspace = true -tokio = { workspace = true, features = ["sync"] } +futures = { workspace = true, optional = true } +tokio = { workspace = true, features = ["sync"], optional = true } # misc auto_impl.workspace = true @@ -43,6 +45,8 @@ tokio = { workspace = true, features = ["full"] } secp256k1 = { workspace = true, features = ["alloc", "recovery", "rand"] } [features] -test-utils = ["reth-consensus/test-utils", "secp256k1", "rand", "parking_lot"] +default = ["p2p"] +p2p = ["tokio", "reth-network-types", "reth-network-api", "reth-eth-wire-types"] +test-utils = ["reth-consensus/test-utils", "secp256k1", "rand", "parking_lot", "tokio"] cli = ["clap"] optimism = ["reth-eth-wire-types/optimism"] diff --git a/crates/interfaces/src/blockchain_tree/error.rs b/crates/interfaces/src/blockchain_tree/error.rs index a98d765014ba..d1245280cec3 100644 --- a/crates/interfaces/src/blockchain_tree/error.rs +++ b/crates/interfaces/src/blockchain_tree/error.rs @@ -394,7 +394,7 @@ impl From for InsertBlockErrorKind { RethError::Consensus(err) => InsertBlockErrorKind::Consensus(err), RethError::Database(err) => InsertBlockErrorKind::Internal(Box::new(err)), RethError::Provider(err) => InsertBlockErrorKind::Internal(Box::new(err)), - RethError::Network(err) => InsertBlockErrorKind::Internal(Box::new(err)), + // RethError::Network(err) => InsertBlockErrorKind::Internal(Box::new(err)), RethError::Custom(err) => InsertBlockErrorKind::Internal(err.into()), RethError::Canonical(err) => InsertBlockErrorKind::Canonical(err), } diff --git a/crates/interfaces/src/error.rs b/crates/interfaces/src/error.rs index 38498c312ab1..301965a00d00 100644 --- a/crates/interfaces/src/error.rs +++ b/crates/interfaces/src/error.rs @@ -5,7 +5,8 @@ use crate::{ provider::ProviderError, }; use reth_consensus::ConsensusError; -use reth_network_api::NetworkError; +// TODO: this needs to be not imported from reth_network_api +// use reth_network_api::NetworkError; use reth_primitives::fs::FsPathError; /// Result alias for [`RethError`]. @@ -35,8 +36,8 @@ pub enum RethError { Provider(#[from] ProviderError), /// Errors related to networking. - #[error(transparent)] - Network(#[from] NetworkError), + // #[error(transparent)] + // Network(#[from] NetworkError), /// Canonical errors encountered. #[error(transparent)] @@ -75,6 +76,6 @@ mod size_asserts { static_assert_size!(ConsensusError, 48); static_assert_size!(DatabaseError, 40); static_assert_size!(ProviderError, 48); - static_assert_size!(NetworkError, 0); + // static_assert_size!(NetworkError, 0); static_assert_size!(CanonicalError, 56); } diff --git a/crates/interfaces/src/lib.rs b/crates/interfaces/src/lib.rs index e60d4a621648..01a677a80d20 100644 --- a/crates/interfaces/src/lib.rs +++ b/crates/interfaces/src/lib.rs @@ -22,6 +22,7 @@ pub mod executor; mod error; pub use error::{RethError, RethResult}; +#[cfg(feature = "p2p")] /// P2P traits. pub mod p2p; diff --git a/testing/zkvm/Cargo.toml b/testing/zkvm/Cargo.toml index e7ff9c0115f1..076b1464459e 100644 --- a/testing/zkvm/Cargo.toml +++ b/testing/zkvm/Cargo.toml @@ -13,4 +13,6 @@ workspace = true [dependencies] sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git" } -reth-primitives = { path = "../../crates/primitives", default_features = false} +reth-primitives = { path = "../../crates/primitives", default-features = false} +reth-consensus.workspace = true +reth-interfaces = { path = "../../crates/interfaces", default-features = false } \ No newline at end of file diff --git a/testing/zkvm/compile.sh b/testing/zkvm/compile.sh index fd1488c330d1..101610d49792 100644 --- a/testing/zkvm/compile.sh +++ b/testing/zkvm/compile.sh @@ -1,48 +1,7 @@ -# CARGO_ENCODED_RUSTFLAGS - - -# // Construct command from the toolchain-specific cargo -# let mut cmd = -# Command::new(cargo.map_or("cargo".to_string(), |c| String::from(c.to_str().unwrap()))); -# // Clear unwanted env vars -# self.sanitize(&mut cmd, true); -# cmd.current_dir(ROOT_DIR.get().unwrap()); - -# // Set Rustc compiler path and flags -# cmd.env( -# "RUSTC", -# rustc.map_or("rustc".to_string(), |c| String::from(c.to_str().unwrap())), -# ); -# if let Some(rust_flags) = rust_flags { -# cmd.env( -# "CARGO_ENCODED_RUSTFLAGS", -# format_flags("-C", &rust_flags).join("\x1f"), -# ); -# } - -# // Set C compiler path and flags -# if let Some(cc_compiler) = cc_compiler { -# cmd.env("CC", cc_compiler); -# } -# if let Some(c_flags) = c_flags { -# cmd.env(format!("CC_{}", self.target), c_flags.join(" ")); -# } - export PATH="/opt/riscv/bin:$PATH" export RUSTUP_TOOLCHAIN="succinct" export RUSTFLAGS="-C passes=loweratomic -C link-arg=-Ttext=0x00200800 -C panic=abort" export CARGO_BUILD_TARGET="riscv32im-succinct-zkvm-elf" export CC="gcc" export CC_riscv32im_succinct_zkvm_elf="/opt/riscv/bin/riscv32-unknown-elf-gcc -mstrict-align" -cargo build --release --ignore-rust-version - - -# export PATH="$HOME/riscv/bin:$PATH" -# export RUSTUP_TOOLCHAIN="succinct" -# export RUSTFLAGS="-C passes=loweratomic -C link-arg=-Ttext=0x00200800 -C panic=abort" -# export CARGO_BUILD_TARGET="riscv32im-succinct-zkvm-elf" -# export CC="gcc" -# export CC_riscv32im_succinct_zkvm_elf="$HOME/riscv/bin/riscv32-unknown-elf-gcc -mstrict-align" -# cargo build --release --ignore-rust-version - -# https://github.com/taikoxyz/raiko/blob/6a8421d5c17a7d8846c22f8f986d9584a6885bf1/script/install.sh#L4 \ No newline at end of file +cargo build --release --ignore-rust-version \ No newline at end of file From ca986df9944ed5aa5a4a3d12ce40117f082edf0f Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 14 May 2024 00:35:56 +0000 Subject: [PATCH 05/30] Now cargo build works in main --- crates/interfaces/Cargo.toml | 2 +- crates/rpc/rpc/src/eth/api/mod.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/interfaces/Cargo.toml b/crates/interfaces/Cargo.toml index 2d63dd1ba7b1..3690189206ad 100644 --- a/crates/interfaces/Cargo.toml +++ b/crates/interfaces/Cargo.toml @@ -20,7 +20,7 @@ reth-network-api = { path = "../net/network-api", optional = true } reth-eth-wire-types = { path = "../net/eth-wire-types", optional = true } # async -futures = { workspace = true, optional = true } +futures = { workspace = true } tokio = { workspace = true, features = ["sync"], optional = true } # misc diff --git a/crates/rpc/rpc/src/eth/api/mod.rs b/crates/rpc/rpc/src/eth/api/mod.rs index 6c936808e996..fb3c0cb14421 100644 --- a/crates/rpc/rpc/src/eth/api/mod.rs +++ b/crates/rpc/rpc/src/eth/api/mod.rs @@ -14,7 +14,7 @@ use crate::eth::{ use async_trait::async_trait; use reth_evm::ConfigureEvm; -use reth_interfaces::RethResult; +use reth_interfaces::{RethError, RethResult}; use reth_network_api::NetworkInfo; use reth_primitives::{ revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg}, @@ -391,7 +391,8 @@ where /// /// Note: This returns an `U64`, since this should return as hex string. async fn protocol_version(&self) -> RethResult { - let status = self.network().network_status().await?; + let status = + self.network().network_status().await.map_err(|_| RethError::Custom("fixme".into()))?; Ok(U64::from(status.protocol_version)) } From eb953b110e37b6b4a48ccac2affece9a392c0eca Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 14 May 2024 00:43:53 +0000 Subject: [PATCH 06/30] now reth_evm compiles --- Cargo.lock | 1 + crates/evm/Cargo.toml | 2 +- testing/zkvm/Cargo.toml | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 961f7ea24e42..10ddfd7b3d6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10751,6 +10751,7 @@ name = "zkvm-test" version = "0.2.0-beta.7" dependencies = [ "reth-consensus", + "reth-evm", "reth-interfaces", "reth-primitives", "sp1-zkvm", diff --git a/crates/evm/Cargo.toml b/crates/evm/Cargo.toml index 854dcd95a20f..1eecbd48fb91 100644 --- a/crates/evm/Cargo.toml +++ b/crates/evm/Cargo.toml @@ -15,7 +15,7 @@ workspace = true reth-primitives.workspace = true revm-primitives.workspace = true revm.workspace = true -reth-interfaces.workspace = true +reth-interfaces = { path = "../interfaces", default-features = false } futures-util.workspace = true parking_lot = { workspace = true, optional = true } diff --git a/testing/zkvm/Cargo.toml b/testing/zkvm/Cargo.toml index 076b1464459e..93fa62d908ce 100644 --- a/testing/zkvm/Cargo.toml +++ b/testing/zkvm/Cargo.toml @@ -15,4 +15,5 @@ workspace = true sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git" } reth-primitives = { path = "../../crates/primitives", default-features = false} reth-consensus.workspace = true -reth-interfaces = { path = "../../crates/interfaces", default-features = false } \ No newline at end of file +reth-interfaces = { path = "../../crates/interfaces", default-features = false } +reth-evm.workspace = true \ No newline at end of file From 150d4a8034534219b3b41d40575cd794a0bc8e87 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 14 May 2024 00:53:46 +0000 Subject: [PATCH 07/30] Added readme --- testing/zkvm/README.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 testing/zkvm/README.md diff --git a/testing/zkvm/README.md b/testing/zkvm/README.md new file mode 100644 index 000000000000..2a0ded0a66d4 --- /dev/null +++ b/testing/zkvm/README.md @@ -0,0 +1,5 @@ +To run testing on a zkVM, you must run on a Linux machine. + +First run `bash install.sh` to download the `riscv-gcc-prebuilt` toolchain. Note that this toolchain is only prebuilt for Linux machines, which is why you're required to use Linux. + +Then, run `bash compile.sh` which will compile with this directory's `Cargo.toml` to the SP1 zkVM. If compilation succeeds, then this means we can use all of those crates within any program written for SP1. \ No newline at end of file From f07e5a9781e34079c46a60ecef4ce1d9f56c2f05 Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Tue, 14 May 2024 02:51:11 +0000 Subject: [PATCH 08/30] progress --- Cargo.lock | 15 + Cargo.toml | 1 + .../provider/src/providers/state/latest.rs | 2 + testing/zkvm-script/Cargo.lock | 740 ++++++++++++++++++ testing/zkvm-script/Cargo.toml | 23 + testing/zkvm-script/README.md | 5 + testing/zkvm-script/src/main.rs | 52 ++ 7 files changed, 838 insertions(+) create mode 100644 testing/zkvm-script/Cargo.lock create mode 100644 testing/zkvm-script/Cargo.toml create mode 100644 testing/zkvm-script/README.md create mode 100644 testing/zkvm-script/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 10ddfd7b3d6f..d23b7065ea5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10746,6 +10746,21 @@ dependencies = [ "syn 2.0.63", ] +[[package]] +name = "zkvm-script" +version = "0.2.0-beta.7" +dependencies = [ + "alloy-provider", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=f1d7085)", + "reth-consensus", + "reth-evm", + "reth-interfaces", + "reth-primitives", + "reth-revm", + "revm", + "url", +] + [[package]] name = "zkvm-test" version = "0.2.0-beta.7" diff --git a/Cargo.toml b/Cargo.toml index 1faaebd503d1..24258996c203 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -93,6 +93,7 @@ members = [ "testing/ef-tests/", "testing/testing-utils", "testing/zkvm", + "testing/zkvm-script" ] default-members = ["bin/reth"] diff --git a/crates/storage/provider/src/providers/state/latest.rs b/crates/storage/provider/src/providers/state/latest.rs index d3c8af6b7fc2..18cae3a4d7a8 100644 --- a/crates/storage/provider/src/providers/state/latest.rs +++ b/crates/storage/provider/src/providers/state/latest.rs @@ -15,6 +15,8 @@ use reth_primitives::{ use reth_trie::{proof::Proof, updates::TrieUpdates, HashedPostState}; use revm::db::BundleState; +// TODO: impl StateProviderRef::new(alloy_provider::Provider) + /// State provider over latest state that takes tx reference. #[derive(Debug)] pub struct LatestStateProviderRef<'b, TX: DbTx> { diff --git a/testing/zkvm-script/Cargo.lock b/testing/zkvm-script/Cargo.lock new file mode 100644 index 000000000000..d50e50e888bc --- /dev/null +++ b/testing/zkvm-script/Cargo.lock @@ -0,0 +1,740 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64ct" +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 = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "tap", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "minimal-reth-program" +version = "0.1.0" +dependencies = [ + "sp1-zkvm", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "scale-info" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.63", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "snowbridge-amcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460a9ed63cdf03c1b9847e8a12a5f5ba19c4efd5869e4a737e05be25d7c427e5" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "sp1-precompiles" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "getrandom", + "hex", + "k256", + "num", + "rand", + "serde", + "snowbridge-amcl", +] + +[[package]] +name = "sp1-zkvm" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +dependencies = [ + "bincode", + "cfg-if", + "getrandom", + "k256", + "libm", + "once_cell", + "rand", + "serde", + "sha2", + "sp1-precompiles", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/testing/zkvm-script/Cargo.toml b/testing/zkvm-script/Cargo.toml new file mode 100644 index 000000000000..542dd0c216cb --- /dev/null +++ b/testing/zkvm-script/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "zkvm-script" +description = "Sample zkVM script" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[lints] +workspace = true + +[dependencies] +reth-primitives = { path = "../../crates/primitives", default-features = false} +reth-consensus.workspace = true +reth-interfaces = { path = "../../crates/interfaces", default-features = false } +reth-evm.workspace = true +revm.workspace = true +alloy-rpc-types.workspace = true +alloy-provider.workspace = true +url.workspace = true +reth-revm.workspace = true \ No newline at end of file diff --git a/testing/zkvm-script/README.md b/testing/zkvm-script/README.md new file mode 100644 index 000000000000..2a0ded0a66d4 --- /dev/null +++ b/testing/zkvm-script/README.md @@ -0,0 +1,5 @@ +To run testing on a zkVM, you must run on a Linux machine. + +First run `bash install.sh` to download the `riscv-gcc-prebuilt` toolchain. Note that this toolchain is only prebuilt for Linux machines, which is why you're required to use Linux. + +Then, run `bash compile.sh` which will compile with this directory's `Cargo.toml` to the SP1 zkVM. If compilation succeeds, then this means we can use all of those crates within any program written for SP1. \ No newline at end of file diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs new file mode 100644 index 000000000000..6d739f4bfde4 --- /dev/null +++ b/testing/zkvm-script/src/main.rs @@ -0,0 +1,52 @@ +//! A simple script that has takes in a block & RPC, fetches the block. + +use alloy_provider::{Provider, ReqwestProvider}; +use alloy_rpc_types::{BlockId, EIP1186AccountProofResponse}; +use reth_revm::database::StateProviderDatabase; +use revm::db::InMemoryDB; +use url::Url; + +struct RpcDb(ReqwestProvider); + +// impl StateProvider for RpcDb { +// fn storage( +// &self, +// account: Address, +// storage_key: StorageKey, +// ) -> ProviderResult> { +// } + +// /// Get account code by its hash +// fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult>; + +// /// Get account and storage proofs. +// fn proof(&self, address: Address, keys: &[B256]) -> ProviderResult; +// } + +async fn execute() { + let block = 1000u64; + let rpc_url = Url::parse("https://example.net").expect("Invalid RPC URL"); + + // Initialize a provider. + let provider = ReqwestProvider::new_http(rpc_url); + + let header = + provider.get_block_by_number(block.into(), false).await.expect("Couldn't fetch block"); + + // Initialize a "provider" DB, where `Database` is implemented with a provider. + // TODO: figure out how to keep track of what accounts are touched and fetch merkle proofs for + // them on the fly. + StateProviderDatabase::new() + + // // Inside the zkVM we will have + // let state_root = ""; // TODO: read in the state root + // let merkle_proofs = vec![]; // TODO: read in the merkle proofs + // let db = WitnessDb::new(state_root, merkle_proofs); + // let executor = + // reth_node_ethereum::EthExecutorProvider::ethereum(ChainSpec::Ethereum).executor(db); + // executor.execute(); + + // verify_against_header(db, finalized_state_root); +} + +fn main() {} From 19892a2edbd56441b4614374508e8d877fcf551d Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Mon, 13 May 2024 21:17:01 -0700 Subject: [PATCH 09/30] compiles --- Cargo.lock | 6 + testing/zkvm-script/Cargo.toml | 10 +- testing/zkvm-script/src/main.rs | 176 ++++++++++++++++++++----- testing/zkvm-script/src/provider_db.rs | 70 ++++++++++ 4 files changed, 230 insertions(+), 32 deletions(-) create mode 100644 testing/zkvm-script/src/provider_db.rs diff --git a/Cargo.lock b/Cargo.lock index d23b7065ea5a..95a5e23b0de2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10752,12 +10752,18 @@ version = "0.2.0-beta.7" dependencies = [ "alloy-provider", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=f1d7085)", + "eyre", "reth-consensus", "reth-evm", "reth-interfaces", + "reth-node-ethereum", "reth-primitives", + "reth-provider", "reth-revm", + "reth-trie", "revm", + "revm-primitives", + "serde_json", "url", ] diff --git a/testing/zkvm-script/Cargo.toml b/testing/zkvm-script/Cargo.toml index 542dd0c216cb..b0e3b77f4acf 100644 --- a/testing/zkvm-script/Cargo.toml +++ b/testing/zkvm-script/Cargo.toml @@ -12,7 +12,7 @@ repository.workspace = true workspace = true [dependencies] -reth-primitives = { path = "../../crates/primitives", default-features = false} +reth-primitives = { path = "../../crates/primitives", default-features = false, features = ["alloy-compat"]} reth-consensus.workspace = true reth-interfaces = { path = "../../crates/interfaces", default-features = false } reth-evm.workspace = true @@ -20,4 +20,10 @@ revm.workspace = true alloy-rpc-types.workspace = true alloy-provider.workspace = true url.workspace = true -reth-revm.workspace = true \ No newline at end of file +reth-revm.workspace = true +reth-provider.workspace = true +reth-node-ethereum.workspace = true +revm-primitives.workspace = true +eyre.workspace = true +serde_json.workspace = true +reth-trie.workspace = true \ No newline at end of file diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index 6d739f4bfde4..c085b571470d 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -1,52 +1,168 @@ //! A simple script that has takes in a block & RPC, fetches the block. +use crate::provider_db::RpcDb; use alloy_provider::{Provider, ReqwestProvider}; -use alloy_rpc_types::{BlockId, EIP1186AccountProofResponse}; +use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse}; +use eyre::Ok; use reth_revm::database::StateProviderDatabase; -use revm::db::InMemoryDB; +use revm::{db::InMemoryDB, Database}; use url::Url; +mod provider_db; +use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; +use reth_interfaces::executor::BlockValidationError; +use reth_node_ethereum::EthereumNode; +use reth_primitives::{Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET}; +use reth_provider::{BundleStateWithReceipts, ProviderError}; +use revm_primitives::{AccountInfo, HashMap, U256}; -struct RpcDb(ReqwestProvider); +pub struct SP1Input { + // The block that will be executed inside the zkVM. + pub block: RethBlock, + // Used for initializing the InMemoryDB inside the zkVM program. + pub merkle_proofs: Vec, + // Code + pub code: Vec>, +} + +struct WitnessDb { + inner: InMemoryDB, + state_root: B256, +} + +impl WitnessDb { + fn new(state_root: B256, merkle_proofs: Vec) -> Self { + let mut inner = InMemoryDB::default(); + for proof in merkle_proofs { + // TODO: verify proof against state_root + // Note that we do not need to hash the code against the code_hash, since + // `insert_contract` already does this. + let address = proof.address; + let account_info = AccountInfo { + nonce: proof.nonce.as_limbs()[0], // Is there a better way to do U64 -> u64? + balance: proof.balance, + code_hash: proof.code_hash, + code: None, // TODO: fill this with code + }; + inner.insert_account_info(address, account_info); + for storage_proof in proof.storage_proof { + // TODO: verify storage proof. + let slot = storage_proof.key.0; + let value = storage_proof.value; + let _ = inner.insert_account_storage(address, slot.into(), value); + } + } + Self { inner, state_root } + } +} + +// TODO: is there some automatic way to implement this? +// TODO: fix all the dummy ProviderError +impl Database for WitnessDb { + type Error = ProviderError; -// impl StateProvider for RpcDb { -// fn storage( -// &self, -// account: Address, -// storage_key: StorageKey, -// ) -> ProviderResult> { -// } + fn basic( + &mut self, + address: revm_primitives::Address, + ) -> Result, Self::Error> { + self.inner.basic(address).map_err(|_| ProviderError::UnsupportedProvider) + } -// /// Get account code by its hash -// fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult>; + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.inner.code_by_hash(code_hash).map_err(|_| ProviderError::UnsupportedProvider) + } -// /// Get account and storage proofs. -// fn proof(&self, address: Address, keys: &[B256]) -> ProviderResult; -// } + fn storage( + &mut self, + address: revm_primitives::Address, + index: revm_primitives::U256, + ) -> Result { + self.inner.storage(address, index).map_err(|_| ProviderError::UnsupportedProvider) + } -async fn execute() { - let block = 1000u64; + fn block_hash(&mut self, number: revm_primitives::U256) -> Result { + self.inner.block_hash(number).map_err(|_| ProviderError::UnsupportedProvider) + } +} + +async fn execute() -> eyre::Result<()> { + let block_number = 1000u64; let rpc_url = Url::parse("https://example.net").expect("Invalid RPC URL"); + let merkle_block_td = U256::from(0); // Initialize a provider. let provider = ReqwestProvider::new_http(rpc_url); - let header = - provider.get_block_by_number(block.into(), false).await.expect("Couldn't fetch block"); + let alloy_block = provider + .get_block_by_number(block_number.into(), false) + .await? + .ok_or(eyre::eyre!("block not found"))?; + + let block = RethBlock::try_from(alloy_block)?; - // Initialize a "provider" DB, where `Database` is implemented with a provider. - // TODO: figure out how to keep track of what accounts are touched and fetch merkle proofs for - // them on the fly. - StateProviderDatabase::new() + let chain_spec = ChainSpecBuilder::default() + .chain(MAINNET.chain) + .genesis( + serde_json::from_str(include_str!( + "../../../crates/ethereum/node/tests/assets/genesis.json" + )) + .unwrap(), + ) + .cancun_activated() + .build(); + let provider_db = RpcDb { provider: provider.clone(), block: block_number.into() }; + let db = StateProviderDatabase::new(provider_db); + let executor = + reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()).executor(db); + let BlockExecutionOutput { state, receipts, .. } = executor.execute( + ( + &block + .clone() + .with_recovered_senders() + .ok_or(BlockValidationError::SenderRecoveryError)?, + (merkle_block_td + block.header.difficulty).into(), + ) + .into(), + )?; + let block_state = BundleStateWithReceipts::new( + state, + Receipts::from_block_receipt(receipts), + block.header.number, + ); - // // Inside the zkVM we will have - // let state_root = ""; // TODO: read in the state root - // let merkle_proofs = vec![]; // TODO: read in the merkle proofs - // let db = WitnessDb::new(state_root, merkle_proofs); - // let executor = - // reth_node_ethereum::EthExecutorProvider::ethereum(ChainSpec::Ethereum).executor(db); - // executor.execute(); + // TODO: how do we compute the new state root here? Is there a way to do this incrementally? + // // Unpacked `BundleState::state_root_slow` function + // let (in_memory_state_root, in_memory_updates) = + // block_state.hash_state_slow().state_root_with_updates(provider.tx_ref())?; + + let next_block = provider + .get_block_by_number((block_number + 1).into(), false) + .await? + .ok_or(eyre::eyre!("next_block not found"))?; + + // Now this is the program inside the zkVM. + let sp1_input = SP1Input { block: block.clone(), merkle_proofs: vec![], code: vec![] }; + let witness_db = WitnessDb::new(sp1_input.block.header.state_root, sp1_input.merkle_proofs); + let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) + .executor(witness_db); + let BlockExecutionOutput { state, receipts, .. } = executor.execute( + ( + &block + .clone() + .with_recovered_senders() + .ok_or(BlockValidationError::SenderRecoveryError)?, + (merkle_block_td + block.header.difficulty).into(), + ) + .into(), + )?; + let block_state = BundleStateWithReceipts::new( + state, + Receipts::from_block_receipt(receipts), + block.header.number, + ); // verify_against_header(db, finalized_state_root); + + Ok(()) } fn main() {} diff --git a/testing/zkvm-script/src/provider_db.rs b/testing/zkvm-script/src/provider_db.rs new file mode 100644 index 000000000000..c5a19bc0f3b6 --- /dev/null +++ b/testing/zkvm-script/src/provider_db.rs @@ -0,0 +1,70 @@ +use alloy_provider::{Provider, ReqwestProvider}; +use reth_interfaces::provider::ProviderResult; +use reth_primitives::{ + trie::AccountProof, Account, Address, BlockHash, BlockId, BlockNumHash, BlockNumber, + BlockNumberOrTag, Bytecode, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, +}; +use reth_provider::{ + AccountReader, BlockHashReader, BlockReader, StateProvider, StateRootProvider, +}; +use reth_trie::updates::TrieUpdates; + +pub struct RpcDb { + pub provider: ReqwestProvider, // TODO: make this a "Provider" + pub block: BlockId, +} + +impl StateProvider for RpcDb { + fn storage( + &self, + account: Address, + storage_key: StorageKey, + ) -> ProviderResult> { + todo!(); + } + + /// Get account code by its hash + fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult> { + unimplemented!(); + } + + /// Get account and storage proofs. + fn proof(&self, address: Address, keys: &[B256]) -> ProviderResult { + todo!(); + } +} + +impl BlockHashReader for RpcDb { + fn block_hash(&self, number: BlockNumber) -> ProviderResult> { + todo!(); + } + + fn canonical_hashes_range( + &self, + start: BlockNumber, + end: BlockNumber, + ) -> reth_interfaces::provider::ProviderResult> { + todo!(); + } +} + +impl AccountReader for RpcDb { + fn basic_account(&self, address: Address) -> ProviderResult> { + todo!(); + } +} + +impl StateRootProvider for RpcDb { + fn state_root(&self, bundle_state: &revm::db::BundleState) -> ProviderResult { + todo!(); + } + + fn state_root_with_updates( + &self, + bundle_state: &revm::db::BundleState, + ) -> reth_interfaces::provider::ProviderResult<(B256, TrieUpdates)> { + todo!(); + } +} + +// TODO: implement BlockReader for RpcDb From 3b3343baa4957774fce1e73284fd28a257e3318d Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Mon, 13 May 2024 21:25:00 -0700 Subject: [PATCH 10/30] compiles again --- testing/zkvm-script/src/main.rs | 43 +++++--------------------- testing/zkvm-script/src/provider_db.rs | 5 ++- testing/zkvm-script/src/witness.rs | 43 ++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 39 deletions(-) create mode 100644 testing/zkvm-script/src/witness.rs diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index c085b571470d..5056cf2d0ea7 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -1,19 +1,21 @@ //! A simple script that has takes in a block & RPC, fetches the block. +mod provider_db; +mod witness; + +use crate::{provider_db::RpcDb, witness::WitnessDb}; -use crate::provider_db::RpcDb; use alloy_provider::{Provider, ReqwestProvider}; use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse}; use eyre::Ok; -use reth_revm::database::StateProviderDatabase; -use revm::{db::InMemoryDB, Database}; -use url::Url; -mod provider_db; use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; use reth_interfaces::executor::BlockValidationError; use reth_node_ethereum::EthereumNode; use reth_primitives::{Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET}; use reth_provider::{BundleStateWithReceipts, ProviderError}; +use reth_revm::database::StateProviderDatabase; +use revm::{db::InMemoryDB, Database}; use revm_primitives::{AccountInfo, HashMap, U256}; +use url::Url; pub struct SP1Input { // The block that will be executed inside the zkVM. @@ -24,37 +26,6 @@ pub struct SP1Input { pub code: Vec>, } -struct WitnessDb { - inner: InMemoryDB, - state_root: B256, -} - -impl WitnessDb { - fn new(state_root: B256, merkle_proofs: Vec) -> Self { - let mut inner = InMemoryDB::default(); - for proof in merkle_proofs { - // TODO: verify proof against state_root - // Note that we do not need to hash the code against the code_hash, since - // `insert_contract` already does this. - let address = proof.address; - let account_info = AccountInfo { - nonce: proof.nonce.as_limbs()[0], // Is there a better way to do U64 -> u64? - balance: proof.balance, - code_hash: proof.code_hash, - code: None, // TODO: fill this with code - }; - inner.insert_account_info(address, account_info); - for storage_proof in proof.storage_proof { - // TODO: verify storage proof. - let slot = storage_proof.key.0; - let value = storage_proof.value; - let _ = inner.insert_account_storage(address, slot.into(), value); - } - } - Self { inner, state_root } - } -} - // TODO: is there some automatic way to implement this? // TODO: fix all the dummy ProviderError impl Database for WitnessDb { diff --git a/testing/zkvm-script/src/provider_db.rs b/testing/zkvm-script/src/provider_db.rs index c5a19bc0f3b6..28107c5bc6f5 100644 --- a/testing/zkvm-script/src/provider_db.rs +++ b/testing/zkvm-script/src/provider_db.rs @@ -10,7 +10,8 @@ use reth_provider::{ use reth_trie::updates::TrieUpdates; pub struct RpcDb { - pub provider: ReqwestProvider, // TODO: make this a "Provider" + // TODO: make this a general "Provider" trait from alloy_provider. + pub provider: ReqwestProvider, pub block: BlockId, } @@ -66,5 +67,3 @@ impl StateRootProvider for RpcDb { todo!(); } } - -// TODO: implement BlockReader for RpcDb diff --git a/testing/zkvm-script/src/witness.rs b/testing/zkvm-script/src/witness.rs new file mode 100644 index 000000000000..84583471e461 --- /dev/null +++ b/testing/zkvm-script/src/witness.rs @@ -0,0 +1,43 @@ +use alloy_provider::{Provider, ReqwestProvider}; +use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse}; +use eyre::Ok; +use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; +use reth_interfaces::executor::BlockValidationError; +use reth_node_ethereum::EthereumNode; +use reth_primitives::{Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET}; +use reth_provider::{BundleStateWithReceipts, ProviderError}; +use reth_revm::database::StateProviderDatabase; +use revm::{db::InMemoryDB, Database}; +use revm_primitives::{AccountInfo, HashMap, U256}; +use url::Url; + +pub struct WitnessDb { + pub inner: InMemoryDB, + pub state_root: B256, +} + +impl WitnessDb { + pub fn new(state_root: B256, merkle_proofs: Vec) -> Self { + let mut inner = InMemoryDB::default(); + for proof in merkle_proofs { + // TODO: verify proof against state_root + // Note that we do not need to hash the code against the code_hash, since + // `insert_contract` already does this. + let address = proof.address; + let account_info = AccountInfo { + nonce: proof.nonce.as_limbs()[0], // Is there a better way to do U64 -> u64? + balance: proof.balance, + code_hash: proof.code_hash, + code: None, // TODO: fill this with code + }; + inner.insert_account_info(address, account_info); + for storage_proof in proof.storage_proof { + // TODO: verify storage proof. + let slot = storage_proof.key.0; + let value = storage_proof.value; + let _ = inner.insert_account_storage(address, slot.into(), value); + } + } + Self { inner, state_root } + } +} From b167865945a9460f06f2d1febac3ed81bc8fe5ba Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Mon, 13 May 2024 21:34:27 -0700 Subject: [PATCH 11/30] compiles --- Cargo.lock | 1 + testing/zkvm-script/Cargo.toml | 3 +- testing/zkvm-script/src/main.rs | 78 ++++++++++++++---------------- testing/zkvm-script/src/witness.rs | 29 +++++++++++ 4 files changed, 68 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 95a5e23b0de2..4129ac967246 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10764,6 +10764,7 @@ dependencies = [ "revm", "revm-primitives", "serde_json", + "tokio", "url", ] diff --git a/testing/zkvm-script/Cargo.toml b/testing/zkvm-script/Cargo.toml index b0e3b77f4acf..aa85516065f5 100644 --- a/testing/zkvm-script/Cargo.toml +++ b/testing/zkvm-script/Cargo.toml @@ -26,4 +26,5 @@ reth-node-ethereum.workspace = true revm-primitives.workspace = true eyre.workspace = true serde_json.workspace = true -reth-trie.workspace = true \ No newline at end of file +reth-trie.workspace = true +tokio.workspace = true \ No newline at end of file diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index 5056cf2d0ea7..f928beffc51b 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -20,44 +20,13 @@ use url::Url; pub struct SP1Input { // The block that will be executed inside the zkVM. pub block: RethBlock, - // Used for initializing the InMemoryDB inside the zkVM program. + // Used for initializing the WitnessDB inside the zkVM program. pub merkle_proofs: Vec, // Code pub code: Vec>, } -// TODO: is there some automatic way to implement this? -// TODO: fix all the dummy ProviderError -impl Database for WitnessDb { - type Error = ProviderError; - - fn basic( - &mut self, - address: revm_primitives::Address, - ) -> Result, Self::Error> { - self.inner.basic(address).map_err(|_| ProviderError::UnsupportedProvider) - } - - fn code_by_hash(&mut self, code_hash: B256) -> Result { - self.inner.code_by_hash(code_hash).map_err(|_| ProviderError::UnsupportedProvider) - } - - fn storage( - &mut self, - address: revm_primitives::Address, - index: revm_primitives::U256, - ) -> Result { - self.inner.storage(address, index).map_err(|_| ProviderError::UnsupportedProvider) - } - - fn block_hash(&mut self, number: revm_primitives::U256) -> Result { - self.inner.block_hash(number).map_err(|_| ProviderError::UnsupportedProvider) - } -} - -async fn execute() -> eyre::Result<()> { - let block_number = 1000u64; - let rpc_url = Url::parse("https://example.net").expect("Invalid RPC URL"); +async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { let merkle_block_td = U256::from(0); // Initialize a provider. @@ -100,18 +69,36 @@ async fn execute() -> eyre::Result<()> { block.header.number, ); - // TODO: how do we compute the new state root here? Is there a way to do this incrementally? - // // Unpacked `BundleState::state_root_slow` function - // let (in_memory_state_root, in_memory_updates) = - // block_state.hash_state_slow().state_root_with_updates(provider.tx_ref())?; - let next_block = provider .get_block_by_number((block_number + 1).into(), false) .await? .ok_or(eyre::eyre!("next_block not found"))?; - // Now this is the program inside the zkVM. + // TODO: how do we compute the new state root here? Is there a way to do this incrementally? + // // Unpacked `BundleState::state_root_slow` function + // let (in_memory_state_root, in_memory_updates) = + // block_state.hash_state_slow().state_root_with_updates(provider.tx_ref())?; + // TODO: check that the computed state_root matches the next_block.header.state_root + let sp1_input = SP1Input { block: block.clone(), merkle_proofs: vec![], code: vec![] }; + Ok(sp1_input) +} + +/// Program that verifies the STF, run inside the zkVM. +fn verify_stf(sp1_input: SP1Input) -> eyre::Result<()> { + let chain_spec = ChainSpecBuilder::default() + .chain(MAINNET.chain) + .genesis( + serde_json::from_str(include_str!( + "../../../crates/ethereum/node/tests/assets/genesis.json" + )) + .unwrap(), + ) + .cancun_activated() + .build(); + let block = sp1_input.block.clone(); + let merkle_block_td = U256::from(0); // TODO: this should be an input? + let witness_db = WitnessDb::new(sp1_input.block.header.state_root, sp1_input.merkle_proofs); let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) .executor(witness_db); @@ -131,9 +118,16 @@ async fn execute() -> eyre::Result<()> { block.header.number, ); - // verify_against_header(db, finalized_state_root); - + // TODO: either return or verify the resulting state root. Ok(()) } -fn main() {} +#[tokio::main] +async fn main() { + let block_number = 1000u64; + let rpc_url = Url::parse("https://example.net").expect("Invalid RPC URL"); + // Get the input. + let sp1_input = get_input(block_number, rpc_url).await.expect("Failed to get input"); + // Verify the STF. + verify_stf(sp1_input).expect("Failed to verify STF"); +} diff --git a/testing/zkvm-script/src/witness.rs b/testing/zkvm-script/src/witness.rs index 84583471e461..9339cf0737af 100644 --- a/testing/zkvm-script/src/witness.rs +++ b/testing/zkvm-script/src/witness.rs @@ -41,3 +41,32 @@ impl WitnessDb { Self { inner, state_root } } } + +// TODO: is there some automatic way to implement this? +// TODO: fix all the dummy ProviderError +impl Database for WitnessDb { + type Error = ProviderError; + + fn basic( + &mut self, + address: revm_primitives::Address, + ) -> Result, Self::Error> { + self.inner.basic(address).map_err(|_| ProviderError::UnsupportedProvider) + } + + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.inner.code_by_hash(code_hash).map_err(|_| ProviderError::UnsupportedProvider) + } + + fn storage( + &mut self, + address: revm_primitives::Address, + index: revm_primitives::U256, + ) -> Result { + self.inner.storage(address, index).map_err(|_| ProviderError::UnsupportedProvider) + } + + fn block_hash(&mut self, number: revm_primitives::U256) -> Result { + self.inner.block_hash(number).map_err(|_| ProviderError::UnsupportedProvider) + } +} From 97305f32448f6aa32fd7daba1ceeac095b12cc79 Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Mon, 13 May 2024 21:48:07 -0700 Subject: [PATCH 12/30] Further cleanup --- testing/zkvm-script/src/main.rs | 19 +++++++++++-------- testing/zkvm-script/src/provider_db.rs | 9 ++++----- testing/zkvm-script/src/witness.rs | 24 +++++++++--------------- 3 files changed, 24 insertions(+), 28 deletions(-) diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index f928beffc51b..c099179c3c4c 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -4,29 +4,30 @@ mod witness; use crate::{provider_db::RpcDb, witness::WitnessDb}; -use alloy_provider::{Provider, ReqwestProvider}; use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse}; use eyre::Ok; use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; use reth_interfaces::executor::BlockValidationError; -use reth_node_ethereum::EthereumNode; use reth_primitives::{Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET}; use reth_provider::{BundleStateWithReceipts, ProviderError}; -use reth_revm::database::StateProviderDatabase; -use revm::{db::InMemoryDB, Database}; -use revm_primitives::{AccountInfo, HashMap, U256}; +use revm_primitives::U256; use url::Url; +/// A struct that holds the input for a zkVM program to execute a block. pub struct SP1Input { - // The block that will be executed inside the zkVM. + /// The block that will be executed inside the zkVM program. pub block: RethBlock, - // Used for initializing the WitnessDB inside the zkVM program. + /// Used forinitializing the WitnessDB inside the zkVM program. pub merkle_proofs: Vec, - // Code + /// A vector of contract bytecode of the same length as [`merkle_proofs`]. pub code: Vec>, } async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { + // We put imports here that are not used in the zkVM program. + use alloy_provider::{Provider, ReqwestProvider}; + use reth_revm::database::StateProviderDatabase; + let merkle_block_td = U256::from(0); // Initialize a provider. @@ -100,6 +101,8 @@ fn verify_stf(sp1_input: SP1Input) -> eyre::Result<()> { let merkle_block_td = U256::from(0); // TODO: this should be an input? let witness_db = WitnessDb::new(sp1_input.block.header.state_root, sp1_input.merkle_proofs); + + // TODO: can we import `EthExecutorProvider` from reth-evm instead of reth-node-ethereum? let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) .executor(witness_db); let BlockExecutionOutput { state, receipts, .. } = executor.execute( diff --git a/testing/zkvm-script/src/provider_db.rs b/testing/zkvm-script/src/provider_db.rs index 28107c5bc6f5..5e9bfc0396a0 100644 --- a/testing/zkvm-script/src/provider_db.rs +++ b/testing/zkvm-script/src/provider_db.rs @@ -1,12 +1,11 @@ +#[allow(unused_imports)] use alloy_provider::{Provider, ReqwestProvider}; use reth_interfaces::provider::ProviderResult; use reth_primitives::{ - trie::AccountProof, Account, Address, BlockHash, BlockId, BlockNumHash, BlockNumber, - BlockNumberOrTag, Bytecode, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, -}; -use reth_provider::{ - AccountReader, BlockHashReader, BlockReader, StateProvider, StateRootProvider, + trie::AccountProof, Account, Address, BlockId, BlockNumber, Bytecode, StorageKey, StorageValue, + B256, }; +use reth_provider::{AccountReader, BlockHashReader, StateProvider, StateRootProvider}; use reth_trie::updates::TrieUpdates; pub struct RpcDb { diff --git a/testing/zkvm-script/src/witness.rs b/testing/zkvm-script/src/witness.rs index 9339cf0737af..72514b11a206 100644 --- a/testing/zkvm-script/src/witness.rs +++ b/testing/zkvm-script/src/witness.rs @@ -1,23 +1,17 @@ -use alloy_provider::{Provider, ReqwestProvider}; -use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse}; -use eyre::Ok; -use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; -use reth_interfaces::executor::BlockValidationError; -use reth_node_ethereum::EthereumNode; -use reth_primitives::{Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET}; -use reth_provider::{BundleStateWithReceipts, ProviderError}; -use reth_revm::database::StateProviderDatabase; +use alloy_rpc_types::EIP1186AccountProofResponse; +use reth_primitives::B256; +// TODO: we need to be able to import `ProviderError` from `reth_provider` in the zkVM. +use reth_provider::ProviderError; use revm::{db::InMemoryDB, Database}; -use revm_primitives::{AccountInfo, HashMap, U256}; -use url::Url; +use revm_primitives::AccountInfo; -pub struct WitnessDb { - pub inner: InMemoryDB, - pub state_root: B256, +pub(crate) struct WitnessDb { + pub(crate) inner: InMemoryDB, + pub(crate) state_root: B256, } impl WitnessDb { - pub fn new(state_root: B256, merkle_proofs: Vec) -> Self { + pub(crate) fn new(state_root: B256, merkle_proofs: Vec) -> Self { let mut inner = InMemoryDB::default(); for proof in merkle_proofs { // TODO: verify proof against state_root From 24639bf580fa00b286b31f567b6d3dc490377edf Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Tue, 14 May 2024 18:42:56 -0700 Subject: [PATCH 13/30] push --- crates/consensus/consensus/Cargo.toml | 3 +-- crates/interfaces/Cargo.toml | 11 +++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/crates/consensus/consensus/Cargo.toml b/crates/consensus/consensus/Cargo.toml index 2ed55e8041fe..308a16f2026e 100644 --- a/crates/consensus/consensus/Cargo.toml +++ b/crates/consensus/consensus/Cargo.toml @@ -11,8 +11,7 @@ repository.workspace = true workspace = true [dependencies] -# reth-primitives.workspace = true -reth-primitives = { path = "../../primitives", default-features = false } +reth-primitives.workspace = true # misc auto_impl.workspace = true diff --git a/crates/interfaces/Cargo.toml b/crates/interfaces/Cargo.toml index 3690189206ad..bd9c94f54b8d 100644 --- a/crates/interfaces/Cargo.toml +++ b/crates/interfaces/Cargo.toml @@ -11,16 +11,15 @@ repository.workspace = true workspace = true [dependencies] +reth-primitives.workspace = true reth-consensus.workspace = true -# Used for p2p feature -reth-primitives = { path = "../primitives", default-features = false } -reth-network-types = { path = "../net/types", optional = true } -reth-network-api = { path = "../net/network-api", optional = true } -reth-eth-wire-types = { path = "../net/eth-wire-types", optional = true } +reth-network-api = { workspace = true, optional = true } +reth-eth-wire-types = { workspace = true, optional = true } +reth-network-types = { workspace = true, optional = true } # async -futures = { workspace = true } +futures.workspace = true tokio = { workspace = true, features = ["sync"], optional = true } # misc From a4b42c0d30f89852c60bc0284594fc6f28489587 Mon Sep 17 00:00:00 2001 From: kaylee Date: Thu, 16 May 2024 03:03:43 +0000 Subject: [PATCH 14/30] Works --- Cargo.toml | 2 +- crates/transaction-pool/Cargo.toml | 2 +- testing/zkvm/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 1faaebd503d1..5777b1fa765a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -255,7 +255,7 @@ reth-network-types = { path = "crates/net/types" } reth-nippy-jar = { path = "crates/storage/nippy-jar" } reth-payload-builder = { path = "crates/payload/builder" } reth-payload-validator = { path = "crates/payload/validator" } -reth-primitives = { path = "crates/primitives" } +reth-primitives = { path = "crates/primitives", default-features = false } reth-provider = { path = "crates/storage/provider" } reth-prune = { path = "crates/prune" } reth-revm = { path = "crates/revm" } diff --git a/crates/transaction-pool/Cargo.toml b/crates/transaction-pool/Cargo.toml index ebb6e497f9aa..6451fcccb8f3 100644 --- a/crates/transaction-pool/Cargo.toml +++ b/crates/transaction-pool/Cargo.toml @@ -14,7 +14,7 @@ workspace = true [dependencies] # reth reth-eth-wire.workspace = true -reth-primitives.workspace = true +reth-primitives = { workspace = true, features = ["default"] } reth-provider.workspace = true reth-tasks.workspace = true revm.workspace = true diff --git a/testing/zkvm/Cargo.toml b/testing/zkvm/Cargo.toml index 93fa62d908ce..dbe698d5041e 100644 --- a/testing/zkvm/Cargo.toml +++ b/testing/zkvm/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git" } -reth-primitives = { path = "../../crates/primitives", default-features = false} +reth-primitives.workspace = true reth-consensus.workspace = true reth-interfaces = { path = "../../crates/interfaces", default-features = false } reth-evm.workspace = true \ No newline at end of file From 8b9ba6224e236aed963482ac246b1b92220aec1f Mon Sep 17 00:00:00 2001 From: kaylee Date: Thu, 16 May 2024 03:27:27 +0000 Subject: [PATCH 15/30] Works with network error not jank --- Cargo.lock | 1 + crates/interfaces/Cargo.toml | 8 ++++---- crates/interfaces/src/blockchain_tree/error.rs | 2 +- crates/interfaces/src/error.rs | 9 ++++----- crates/net/network-api/src/lib.rs | 5 +---- crates/net/network/src/network.rs | 5 ++--- crates/net/types/Cargo.toml | 1 + crates/net/{network-api => types}/src/error.rs | 0 crates/net/types/src/lib.rs | 4 ++++ crates/rpc/rpc/src/result.rs | 2 +- 10 files changed, 19 insertions(+), 18 deletions(-) rename crates/net/{network-api => types}/src/error.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 10ddfd7b3d6f..6c288fc68c34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7240,6 +7240,7 @@ dependencies = [ "serde_json", "serde_with", "thiserror", + "tokio", "url", ] diff --git a/crates/interfaces/Cargo.toml b/crates/interfaces/Cargo.toml index bd9c94f54b8d..e4da09df2d16 100644 --- a/crates/interfaces/Cargo.toml +++ b/crates/interfaces/Cargo.toml @@ -13,14 +13,14 @@ workspace = true [dependencies] reth-primitives.workspace = true reth-consensus.workspace = true +reth-network-types.workspace = true reth-network-api = { workspace = true, optional = true } reth-eth-wire-types = { workspace = true, optional = true } -reth-network-types = { workspace = true, optional = true } # async futures.workspace = true -tokio = { workspace = true, features = ["sync"], optional = true } +tokio = { workspace = true, features = ["sync"] } # misc auto_impl.workspace = true @@ -45,7 +45,7 @@ secp256k1 = { workspace = true, features = ["alloc", "recovery", "rand"] } [features] default = ["p2p"] -p2p = ["tokio", "reth-network-types", "reth-network-api", "reth-eth-wire-types"] -test-utils = ["reth-consensus/test-utils", "secp256k1", "rand", "parking_lot", "tokio"] +p2p = ["reth-network-api", "reth-eth-wire-types"] +test-utils = ["reth-consensus/test-utils", "secp256k1", "rand", "parking_lot"] cli = ["clap"] optimism = ["reth-eth-wire-types/optimism"] diff --git a/crates/interfaces/src/blockchain_tree/error.rs b/crates/interfaces/src/blockchain_tree/error.rs index d1245280cec3..a98d765014ba 100644 --- a/crates/interfaces/src/blockchain_tree/error.rs +++ b/crates/interfaces/src/blockchain_tree/error.rs @@ -394,7 +394,7 @@ impl From for InsertBlockErrorKind { RethError::Consensus(err) => InsertBlockErrorKind::Consensus(err), RethError::Database(err) => InsertBlockErrorKind::Internal(Box::new(err)), RethError::Provider(err) => InsertBlockErrorKind::Internal(Box::new(err)), - // RethError::Network(err) => InsertBlockErrorKind::Internal(Box::new(err)), + RethError::Network(err) => InsertBlockErrorKind::Internal(Box::new(err)), RethError::Custom(err) => InsertBlockErrorKind::Internal(err.into()), RethError::Canonical(err) => InsertBlockErrorKind::Canonical(err), } diff --git a/crates/interfaces/src/error.rs b/crates/interfaces/src/error.rs index 301965a00d00..92fcd8e1cae8 100644 --- a/crates/interfaces/src/error.rs +++ b/crates/interfaces/src/error.rs @@ -5,8 +5,7 @@ use crate::{ provider::ProviderError, }; use reth_consensus::ConsensusError; -// TODO: this needs to be not imported from reth_network_api -// use reth_network_api::NetworkError; +use reth_network_types::NetworkError; use reth_primitives::fs::FsPathError; /// Result alias for [`RethError`]. @@ -36,8 +35,8 @@ pub enum RethError { Provider(#[from] ProviderError), /// Errors related to networking. - // #[error(transparent)] - // Network(#[from] NetworkError), + #[error(transparent)] + Network(#[from] NetworkError), /// Canonical errors encountered. #[error(transparent)] @@ -76,6 +75,6 @@ mod size_asserts { static_assert_size!(ConsensusError, 48); static_assert_size!(DatabaseError, 40); static_assert_size!(ProviderError, 48); - // static_assert_size!(NetworkError, 0); + static_assert_size!(NetworkError, 0); static_assert_size!(CanonicalError, 56); } diff --git a/crates/net/network-api/src/lib.rs b/crates/net/network-api/src/lib.rs index 6c3040bd9b82..ba014f19fe98 100644 --- a/crates/net/network-api/src/lib.rs +++ b/crates/net/network-api/src/lib.rs @@ -14,17 +14,14 @@ #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] use reth_eth_wire::{DisconnectReason, EthVersion, Status}; -use reth_network_types::PeerId; +use reth_network_types::{NetworkError, PeerId}; use reth_primitives::NodeRecord; use std::{future::Future, net::SocketAddr, sync::Arc, time::Instant}; -pub use error::NetworkError; pub use reputation::{Reputation, ReputationChangeKind}; use reth_eth_wire::capability::Capabilities; use reth_rpc_types::NetworkStatus; -/// Network Error -pub mod error; /// Reputation score pub mod reputation; diff --git a/crates/net/network/src/network.rs b/crates/net/network/src/network.rs index 86669bf19f48..2d79bf129968 100644 --- a/crates/net/network/src/network.rs +++ b/crates/net/network/src/network.rs @@ -10,10 +10,9 @@ use reth_eth_wire::{DisconnectReason, NewBlock, NewPooledTransactionHashes, Shar use reth_interfaces::sync::{NetworkSyncUpdater, SyncState, SyncStateProvider}; use reth_net_common::bandwidth_meter::BandwidthMeter; use reth_network_api::{ - NetworkError, NetworkInfo, PeerInfo, PeerKind, Peers, PeersInfo, Reputation, - ReputationChangeKind, + NetworkInfo, PeerInfo, PeerKind, Peers, PeersInfo, Reputation, ReputationChangeKind, }; -use reth_network_types::PeerId; +use reth_network_types::{NetworkError, PeerId}; use reth_primitives::{Head, NodeRecord, TransactionSigned, B256}; use reth_rpc_types::NetworkStatus; use secp256k1::SecretKey; diff --git a/crates/net/types/Cargo.toml b/crates/net/types/Cargo.toml index 9be9a2f3a228..7a7a4fcbc069 100644 --- a/crates/net/types/Cargo.toml +++ b/crates/net/types/Cargo.toml @@ -17,6 +17,7 @@ workspace = true alloy-primitives = { workspace = true, features = ["rlp"] } alloy-rlp = { workspace = true, features = ["derive"] } enr.workspace = true +tokio.workspace = true # crypto secp256k1.workspace = true diff --git a/crates/net/network-api/src/error.rs b/crates/net/types/src/error.rs similarity index 100% rename from crates/net/network-api/src/error.rs rename to crates/net/types/src/error.rs diff --git a/crates/net/types/src/lib.rs b/crates/net/types/src/lib.rs index e4b9f28a4fdc..dfc6ff496277 100644 --- a/crates/net/types/src/lib.rs +++ b/crates/net/types/src/lib.rs @@ -21,6 +21,10 @@ pub use enr::Enr; /// Alias for a peer identifier pub type PeerId = B512; +/// Network Error. +pub mod error; +pub use error::NetworkError; + pub mod node_record; pub use node_record::{NodeRecord, NodeRecordParseError}; diff --git a/crates/rpc/rpc/src/result.rs b/crates/rpc/rpc/src/result.rs index 677b537adea6..a4beac694944 100644 --- a/crates/rpc/rpc/src/result.rs +++ b/crates/rpc/rpc/src/result.rs @@ -101,7 +101,7 @@ macro_rules! impl_to_rpc_result { impl_to_rpc_result!(PayloadError); impl_to_rpc_result!(reth_interfaces::RethError); impl_to_rpc_result!(reth_interfaces::provider::ProviderError); -impl_to_rpc_result!(reth_network_api::NetworkError); +impl_to_rpc_result!(reth_network_types::NetworkError); /// Constructs an invalid params JSON-RPC error. pub(crate) fn invalid_params_rpc_err( From e0e7df48cc77830069f4a15f8217f90bff4e92f4 Mon Sep 17 00:00:00 2001 From: kaylee Date: Thu, 16 May 2024 03:42:03 +0000 Subject: [PATCH 16/30] Cleaned --- Cargo.toml | 2 +- crates/evm/Cargo.toml | 2 +- crates/interfaces/Cargo.toml | 8 ++++---- crates/net/types/Cargo.toml | 2 +- crates/rpc/rpc/src/eth/api/mod.rs | 5 ++--- crates/storage/provider/Cargo.toml | 2 +- testing/zkvm/Cargo.toml | 2 +- 7 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5777b1fa765a..988e8978ee94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -241,7 +241,7 @@ reth-evm = { path = "crates/evm" } reth-evm-ethereum = { path = "crates/ethereum/evm" } reth-exex = { path = "crates/exex" } reth-optimism-payload-builder = { path = "crates/optimism/payload" } -reth-interfaces = { path = "crates/interfaces" } +reth-interfaces = { path = "crates/interfaces", default-features = false } reth-ipc = { path = "crates/rpc/ipc" } reth-libmdbx = { path = "crates/storage/libmdbx-rs" } reth-mdbx-sys = { path = "crates/storage/libmdbx-rs/mdbx-sys" } diff --git a/crates/evm/Cargo.toml b/crates/evm/Cargo.toml index 1eecbd48fb91..854dcd95a20f 100644 --- a/crates/evm/Cargo.toml +++ b/crates/evm/Cargo.toml @@ -15,7 +15,7 @@ workspace = true reth-primitives.workspace = true revm-primitives.workspace = true revm.workspace = true -reth-interfaces = { path = "../interfaces", default-features = false } +reth-interfaces.workspace = true futures-util.workspace = true parking_lot = { workspace = true, optional = true } diff --git a/crates/interfaces/Cargo.toml b/crates/interfaces/Cargo.toml index e4da09df2d16..00e94dcf5c0d 100644 --- a/crates/interfaces/Cargo.toml +++ b/crates/interfaces/Cargo.toml @@ -19,13 +19,13 @@ reth-network-api = { workspace = true, optional = true } reth-eth-wire-types = { workspace = true, optional = true } # async -futures.workspace = true -tokio = { workspace = true, features = ["sync"] } +futures = { workspace = true, optional = true } +tokio = { workspace = true, features = ["sync"], optional = true } # misc auto_impl.workspace = true thiserror.workspace = true -tracing.workspace = true +tracing = { workspace = true, optional = true } secp256k1 = { workspace = true, default-features = false, features = [ "alloc", "recovery", @@ -45,7 +45,7 @@ secp256k1 = { workspace = true, features = ["alloc", "recovery", "rand"] } [features] default = ["p2p"] -p2p = ["reth-network-api", "reth-eth-wire-types"] +p2p = ["reth-network-api", "reth-eth-wire-types", "tracing", "tokio", "futures" ] test-utils = ["reth-consensus/test-utils", "secp256k1", "rand", "parking_lot"] cli = ["clap"] optimism = ["reth-eth-wire-types/optimism"] diff --git a/crates/net/types/Cargo.toml b/crates/net/types/Cargo.toml index 7a7a4fcbc069..c9cb3e5a93ab 100644 --- a/crates/net/types/Cargo.toml +++ b/crates/net/types/Cargo.toml @@ -17,7 +17,7 @@ workspace = true alloy-primitives = { workspace = true, features = ["rlp"] } alloy-rlp = { workspace = true, features = ["derive"] } enr.workspace = true -tokio.workspace = true +tokio = { workspace = true, features = ["sync"] } # crypto secp256k1.workspace = true diff --git a/crates/rpc/rpc/src/eth/api/mod.rs b/crates/rpc/rpc/src/eth/api/mod.rs index fb3c0cb14421..6c936808e996 100644 --- a/crates/rpc/rpc/src/eth/api/mod.rs +++ b/crates/rpc/rpc/src/eth/api/mod.rs @@ -14,7 +14,7 @@ use crate::eth::{ use async_trait::async_trait; use reth_evm::ConfigureEvm; -use reth_interfaces::{RethError, RethResult}; +use reth_interfaces::RethResult; use reth_network_api::NetworkInfo; use reth_primitives::{ revm_primitives::{BlockEnv, CfgEnvWithHandlerCfg}, @@ -391,8 +391,7 @@ where /// /// Note: This returns an `U64`, since this should return as hex string. async fn protocol_version(&self) -> RethResult { - let status = - self.network().network_status().await.map_err(|_| RethError::Custom("fixme".into()))?; + let status = self.network().network_status().await?; Ok(U64::from(status.protocol_version)) } diff --git a/crates/storage/provider/Cargo.toml b/crates/storage/provider/Cargo.toml index 1272a824c34b..3c288b00cbe5 100644 --- a/crates/storage/provider/Cargo.toml +++ b/crates/storage/provider/Cargo.toml @@ -14,7 +14,7 @@ workspace = true [dependencies] # reth reth-primitives.workspace = true -reth-interfaces.workspace = true +reth-interfaces = { workspace = true, features = ["p2p"] } reth-db.workspace = true reth-trie = { workspace = true, features = ["metrics"] } reth-nippy-jar.workspace = true diff --git a/testing/zkvm/Cargo.toml b/testing/zkvm/Cargo.toml index dbe698d5041e..b96255f18339 100644 --- a/testing/zkvm/Cargo.toml +++ b/testing/zkvm/Cargo.toml @@ -15,5 +15,5 @@ workspace = true sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git" } reth-primitives.workspace = true reth-consensus.workspace = true -reth-interfaces = { path = "../../crates/interfaces", default-features = false } +reth-interfaces.workspace = true reth-evm.workspace = true \ No newline at end of file From bbd144a2c6d8232aec641e06e8447eae3ab81a10 Mon Sep 17 00:00:00 2001 From: kaylee Date: Thu, 16 May 2024 03:48:06 +0000 Subject: [PATCH 17/30] Cleanup top level --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 988e8978ee94..1faaebd503d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -241,7 +241,7 @@ reth-evm = { path = "crates/evm" } reth-evm-ethereum = { path = "crates/ethereum/evm" } reth-exex = { path = "crates/exex" } reth-optimism-payload-builder = { path = "crates/optimism/payload" } -reth-interfaces = { path = "crates/interfaces", default-features = false } +reth-interfaces = { path = "crates/interfaces" } reth-ipc = { path = "crates/rpc/ipc" } reth-libmdbx = { path = "crates/storage/libmdbx-rs" } reth-mdbx-sys = { path = "crates/storage/libmdbx-rs/mdbx-sys" } @@ -255,7 +255,7 @@ reth-network-types = { path = "crates/net/types" } reth-nippy-jar = { path = "crates/storage/nippy-jar" } reth-payload-builder = { path = "crates/payload/builder" } reth-payload-validator = { path = "crates/payload/validator" } -reth-primitives = { path = "crates/primitives", default-features = false } +reth-primitives = { path = "crates/primitives" } reth-provider = { path = "crates/storage/provider" } reth-prune = { path = "crates/prune" } reth-revm = { path = "crates/revm" } From 29ba66e04a728d1833dc846a3b7765716d896995 Mon Sep 17 00:00:00 2001 From: kaylee Date: Thu, 16 May 2024 04:40:18 +0000 Subject: [PATCH 18/30] Cleanup more --- .github/workflows/integration.yml | 13 ++++++++ Cargo.toml | 2 +- Dockerfile.zkvm | 25 +++++++++++++++ crates/interfaces/Cargo.toml | 2 +- testing/zkvm/README.md | 6 +--- testing/zkvm/compile.sh | 7 ----- testing/zkvm/elf/riscv32im-succinct-zkvm-elf | Bin 127664 -> 0 bytes testing/zkvm/install.sh | 31 ------------------- testing/zkvm/src/main.rs | 19 ++---------- 9 files changed, 43 insertions(+), 62 deletions(-) create mode 100644 Dockerfile.zkvm delete mode 100644 testing/zkvm/compile.sh delete mode 100755 testing/zkvm/elf/riscv32im-succinct-zkvm-elf delete mode 100644 testing/zkvm/install.sh diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 319896154b19..3f3a1d08e03a 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -89,3 +89,16 @@ jobs: uses: re-actors/alls-green@release/v1 with: jobs: ${{ toJSON(needs) }} + + zkvm: + name: zkVM compilation + # Only run sync tests in merge groups + if: github.event_name == 'merge_group' + runs-on: + group: Reth + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + - name: Run zkVM compilation + run: | + docker build -t zkvm_image -f Dockerfile.zkvm . \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index 1faaebd503d1..5777b1fa765a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -255,7 +255,7 @@ reth-network-types = { path = "crates/net/types" } reth-nippy-jar = { path = "crates/storage/nippy-jar" } reth-payload-builder = { path = "crates/payload/builder" } reth-payload-validator = { path = "crates/payload/validator" } -reth-primitives = { path = "crates/primitives" } +reth-primitives = { path = "crates/primitives", default-features = false } reth-provider = { path = "crates/storage/provider" } reth-prune = { path = "crates/prune" } reth-revm = { path = "crates/revm" } diff --git a/Dockerfile.zkvm b/Dockerfile.zkvm new file mode 100644 index 000000000000..926fc1c167f5 --- /dev/null +++ b/Dockerfile.zkvm @@ -0,0 +1,25 @@ +FROM lukemathwalker/cargo-chef:latest-rust-1 AS chef + +# Install system dependencies +RUN apt-get update && apt-get -y upgrade && apt-get install -y libclang-dev pkg-config + +# Install the Succinct toolchain +RUN curl -L https://sp1.succinct.xyz | bash +RUN /root/.sp1/bin/sp1up + +# Install the RISC-V toolchain for gcc, used for compiling libraries with C dependencies. +RUN mkdir -p /opt/riscv +RUN wget -O /tmp/riscv32-unknown-elf.gcc-13.2.0.tar.gz https://github.com/stnolting/riscv-gcc-prebuilt/releases/download/rv32i-131023/riscv32-unknown-elf.gcc-13.2.0.tar.gz +RUN tar -xzf /tmp/riscv32-unknown-elf.gcc-13.2.0.tar.gz -C /opt/riscv/ + +WORKDIR /opt/riscv + +COPY . . + +ENV RUSTUP_TOOLCHAIN="succinct" +ENV RUSTFLAGS="-C passes=loweratomic -C link-arg=-Ttext=0x00200800 -C panic=abort" +ENV CARGO_BUILD_TARGET="riscv32im-succinct-zkvm-elf" +ENV CC="gcc" +ENV CC_riscv32im_succinct_zkvm_elf="/opt/riscv/bin/riscv32-unknown-elf-gcc -mstrict-align" + +RUN cargo build -p zkvm-test --release --ignore-rust-version \ No newline at end of file diff --git a/crates/interfaces/Cargo.toml b/crates/interfaces/Cargo.toml index 00e94dcf5c0d..3491bf39a7b6 100644 --- a/crates/interfaces/Cargo.toml +++ b/crates/interfaces/Cargo.toml @@ -44,7 +44,7 @@ tokio = { workspace = true, features = ["full"] } secp256k1 = { workspace = true, features = ["alloc", "recovery", "rand"] } [features] -default = ["p2p"] +default = [] p2p = ["reth-network-api", "reth-eth-wire-types", "tracing", "tokio", "futures" ] test-utils = ["reth-consensus/test-utils", "secp256k1", "rand", "parking_lot"] cli = ["clap"] diff --git a/testing/zkvm/README.md b/testing/zkvm/README.md index 2a0ded0a66d4..f3211300af23 100644 --- a/testing/zkvm/README.md +++ b/testing/zkvm/README.md @@ -1,5 +1 @@ -To run testing on a zkVM, you must run on a Linux machine. - -First run `bash install.sh` to download the `riscv-gcc-prebuilt` toolchain. Note that this toolchain is only prebuilt for Linux machines, which is why you're required to use Linux. - -Then, run `bash compile.sh` which will compile with this directory's `Cargo.toml` to the SP1 zkVM. If compilation succeeds, then this means we can use all of those crates within any program written for SP1. \ No newline at end of file +This has a sample `Cargo.toml` with all crates from `reth` that we want to compile within a zkVM. The `Dockerfile.zkvm` in the workspace directory contains an environment that ensures that this package will compile to a `RISC-V 32` toolchain. \ No newline at end of file diff --git a/testing/zkvm/compile.sh b/testing/zkvm/compile.sh deleted file mode 100644 index 101610d49792..000000000000 --- a/testing/zkvm/compile.sh +++ /dev/null @@ -1,7 +0,0 @@ -export PATH="/opt/riscv/bin:$PATH" -export RUSTUP_TOOLCHAIN="succinct" -export RUSTFLAGS="-C passes=loweratomic -C link-arg=-Ttext=0x00200800 -C panic=abort" -export CARGO_BUILD_TARGET="riscv32im-succinct-zkvm-elf" -export CC="gcc" -export CC_riscv32im_succinct_zkvm_elf="/opt/riscv/bin/riscv32-unknown-elf-gcc -mstrict-align" -cargo build --release --ignore-rust-version \ No newline at end of file diff --git a/testing/zkvm/elf/riscv32im-succinct-zkvm-elf b/testing/zkvm/elf/riscv32im-succinct-zkvm-elf deleted file mode 100755 index e9f3e1c3b9e2ca237a312ea253021be9c3c92b1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 127664 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 diff --git a/testing/zkvm/install.sh b/testing/zkvm/install.sh deleted file mode 100644 index d297735eb6a0..000000000000 --- a/testing/zkvm/install.sh +++ /dev/null @@ -1,31 +0,0 @@ -# From Raiko -# https://github.com/taikoxyz/raiko/blob/6a8421d5c17a7d8846c22f8f986d9584a6885bf1/script/install.sh - -#!/usr/bin/env bash - -# Any error will result in failure -set -e - -# Check if the RISC-V GCC prebuilt binary archive already exists -if [ -f /tmp/riscv32-unknown-elf.gcc-13.2.0.tar.gz ]; then - echo "riscv-gcc-prebuilt existed, please check the file manually" -else - # Download the file using wget - wget -O /tmp/riscv32-unknown-elf.gcc-13.2.0.tar.gz https://github.com/stnolting/riscv-gcc-prebuilt/releases/download/rv32i-131023/riscv32-unknown-elf.gcc-13.2.0.tar.gz - # Check if wget succeeded - if [ $? -ne 0 ]; then - echo "Failed to download riscv-gcc-prebuilt" - exit 1 - fi - # Create the directory if it doesn't exist - if [ ! -d /opt/riscv ]; then - mkdir /opt/riscv - fi - # Extract the downloaded archive - tar -xzf /tmp/riscv32-unknown-elf.gcc-13.2.0.tar.gz -C /opt/riscv/ - # Check if tar succeeded - if [ $? -ne 0 ]; then - echo "Failed to extract riscv-gcc-prebuilt" - exit 1 - fi -fi diff --git a/testing/zkvm/src/main.rs b/testing/zkvm/src/main.rs index 8bcb12df9d0c..d4208a599b78 100644 --- a/testing/zkvm/src/main.rs +++ b/testing/zkvm/src/main.rs @@ -3,20 +3,5 @@ #![no_main] sp1_zkvm::entrypoint!(main); -pub fn main() { - // NOTE: values of n larger than 186 will overflow the u128 type, - // resulting in output that doesn't match fibonacci sequence. - // However, the resulting proof will still be valid! - let n = sp1_zkvm::io::read::(); - let mut a: u128 = 0; - let mut b: u128 = 1; - let mut sum: u128; - for _ in 1..n { - sum = a + b; - a = b; - b = sum; - } - - sp1_zkvm::io::commit(&a); - sp1_zkvm::io::commit(&b); -} +/// The main entrypoint for the zkVM program. +pub fn main() {} From d7aa5c4e2a5a9c1f9ffefb119e4d1cf698de4149 Mon Sep 17 00:00:00 2001 From: kaylee Date: Thu, 16 May 2024 04:52:49 +0000 Subject: [PATCH 19/30] Works --- Cargo.lock | 3 ++- Cargo.toml | 3 --- testing/zkvm/Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c288fc68c34..7472d87c615a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1493,7 +1493,8 @@ dependencies = [ [[package]] name = "c-kzg" version = "1.0.2" -source = "git+https://github.com/sp1-patches/c-kzg-4844?branch=uma/remove-taiko#ba2780307b218dd36851a22708f722b03b2f23a1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf100c4cea8f207e883ff91ca886d621d8a166cb04971dfaa9bb8fd99ed95df" dependencies = [ "blst", "cc", diff --git a/Cargo.toml b/Cargo.toml index 5777b1fa765a..472b6673b9f0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -402,6 +402,3 @@ proptest-derive = "0.4" serial_test = "3" similar-asserts = "1.5.0" test-fuzz = "5" - -[patch.crates-io] -c-kzg = { git = "https://github.com/sp1-patches/c-kzg-4844", branch = "uma/remove-taiko" } \ No newline at end of file diff --git a/testing/zkvm/Cargo.toml b/testing/zkvm/Cargo.toml index b96255f18339..3dbc884570c2 100644 --- a/testing/zkvm/Cargo.toml +++ b/testing/zkvm/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git" } -reth-primitives.workspace = true +reth-primitives.workspace = true reth-consensus.workspace = true reth-interfaces.workspace = true reth-evm.workspace = true \ No newline at end of file From a760f704420592bb6a04494b65c698ad140a83a4 Mon Sep 17 00:00:00 2001 From: kaylee Date: Thu, 16 May 2024 05:09:21 +0000 Subject: [PATCH 20/30] Update lock --- Cargo.lock | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7472d87c615a..0ac5a5cfd2a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -146,7 +146,7 @@ dependencies = [ [[package]] name = "alloy-consensus" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" +source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" dependencies = [ "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", "alloy-primitives", @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "alloy-eips" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" +source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -222,7 +222,7 @@ dependencies = [ [[package]] name = "alloy-genesis" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" +source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" dependencies = [ "alloy-primitives", "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy)", @@ -408,7 +408,7 @@ dependencies = [ [[package]] name = "alloy-rpc-types" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" +source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" dependencies = [ "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy)", "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy)", @@ -490,7 +490,7 @@ dependencies = [ [[package]] name = "alloy-serde" version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy#c07aaee636212fc2601a3c694e78846e84a65451" +source = "git+https://github.com/alloy-rs/alloy#af25c53f99a4549ece47625b7d65f088c3487864" dependencies = [ "alloy-primitives", "serde", @@ -897,9 +897,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "2.3.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f2776ead772134d55b62dd45e59a79e21612d85d0af729b8b7d3967d601a62a" +checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" dependencies = [ "concurrent-queue", "event-listener 5.3.0", @@ -1248,7 +1248,7 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" dependencies = [ - "async-channel 2.3.0", + "async-channel 2.2.1", "async-lock", "async-task", "futures-io", @@ -3080,9 +3080,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.9" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" +checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" [[package]] name = "findshlibs" @@ -3495,9 +3495,9 @@ dependencies = [ [[package]] name = "hashlink" -version = "0.9.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +checksum = "692eaaf7f7607518dd3cef090f1474b61edc5301d8012f09579920df68b725ee" dependencies = [ "hashbrown 0.14.5", ] @@ -5702,9 +5702,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464db0c665917b13ebb5d453ccdec4add5658ee1adc7affc7677615356a8afaf" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" dependencies = [ "atomic-waker", "fastrand 2.1.0", @@ -8317,7 +8317,7 @@ dependencies = [ "bitflags 2.5.0", "fallible-iterator", "fallible-streaming-iterator", - "hashlink 0.9.1", + "hashlink 0.9.0", "libsqlite3-sys", "smallvec", ] @@ -9080,7 +9080,7 @@ dependencies = [ [[package]] name = "sp1-precompiles" version = "0.1.0" -source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +source = "git+https://github.com/succinctlabs/sp1.git#f50fb1c3b11993fa926c128b1d38db7af969ef51" dependencies = [ "anyhow", "bincode", @@ -9097,7 +9097,7 @@ dependencies = [ [[package]] name = "sp1-zkvm" version = "0.1.0" -source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +source = "git+https://github.com/succinctlabs/sp1.git#f50fb1c3b11993fa926c128b1d38db7af969ef51" dependencies = [ "bincode", "cfg-if", @@ -10218,9 +10218,9 @@ dependencies = [ [[package]] name = "waker-fn" -version = "1.2.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "walkdir" From c26667eae64ae020516dca4af51fca682b4bae69 Mon Sep 17 00:00:00 2001 From: kaylee Date: Thu, 16 May 2024 05:11:01 +0000 Subject: [PATCH 21/30] rev --- Cargo.lock | 4 ++-- testing/zkvm/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ac5a5cfd2a2..706911642eb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9080,7 +9080,7 @@ dependencies = [ [[package]] name = "sp1-precompiles" version = "0.1.0" -source = "git+https://github.com/succinctlabs/sp1.git#f50fb1c3b11993fa926c128b1d38db7af969ef51" +source = "git+https://github.com/succinctlabs/sp1.git?rev=v1.0.0-testnet#e721b246243e40376f7b75d7330e53c7351b727f" dependencies = [ "anyhow", "bincode", @@ -9097,7 +9097,7 @@ dependencies = [ [[package]] name = "sp1-zkvm" version = "0.1.0" -source = "git+https://github.com/succinctlabs/sp1.git#f50fb1c3b11993fa926c128b1d38db7af969ef51" +source = "git+https://github.com/succinctlabs/sp1.git?rev=v1.0.0-testnet#e721b246243e40376f7b75d7330e53c7351b727f" dependencies = [ "bincode", "cfg-if", diff --git a/testing/zkvm/Cargo.toml b/testing/zkvm/Cargo.toml index 3dbc884570c2..547ec1d00862 100644 --- a/testing/zkvm/Cargo.toml +++ b/testing/zkvm/Cargo.toml @@ -12,7 +12,7 @@ repository.workspace = true workspace = true [dependencies] -sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git" } +sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git", rev = "v1.0.0-testnet" } reth-primitives.workspace = true reth-consensus.workspace = true reth-interfaces.workspace = true From ce83aae70744674ebb767378db7495c661d21827 Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Thu, 16 May 2024 21:56:34 -0700 Subject: [PATCH 22/30] cleanup --- Cargo.lock | 386 ++++++++++++++++++++++++- Cargo.toml | 3 +- testing/zkvm-script/Cargo.toml | 6 +- testing/zkvm-script/src/main.rs | 64 +++- testing/zkvm-script/src/provider_db.rs | 116 +++++--- 5 files changed, 509 insertions(+), 66 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f6c33d25dd85..861d4f1fb631 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -988,6 +988,17 @@ dependencies = [ "syn 2.0.63", ] +[[package]] +name = "async_io_stream" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +dependencies = [ + "futures", + "pharos", + "rustc_version 0.4.0", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -2559,7 +2570,7 @@ dependencies = [ "alloy-rlp", "arrayvec", "delay_map", - "enr", + "enr 0.12.0", "fnv", "futures", "hashlink 0.8.4", @@ -2744,6 +2755,24 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +[[package]] +name = "enr" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a3d8dc56e02f954cac8eb489772c552c473346fc34f67412bb6244fd647f7e4" +dependencies = [ + "base64 0.21.7", + "bytes", + "hex", + "k256", + "log", + "rand 0.8.5", + "rlp", + "serde", + "sha3", + "zeroize", +] + [[package]] name = "enr" version = "0.12.0" @@ -2828,6 +2857,23 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "ethabi" +version = "18.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" +dependencies = [ + "ethereum-types", + "hex", + "once_cell", + "regex", + "serde", + "serde_json", + "sha3", + "thiserror", + "uint", +] + [[package]] name = "ethbloom" version = "0.13.0" @@ -2836,8 +2882,10 @@ checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" dependencies = [ "crunchy", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "tiny-keccak", ] @@ -2849,9 +2897,11 @@ checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" dependencies = [ "ethbloom", "fixed-hash", + "impl-codec", "impl-rlp", "impl-serde", "primitive-types", + "scale-info", "uint", ] @@ -2878,6 +2928,71 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "ethers-core" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d80cc6ad30b14a48ab786523af33b37f28a8623fc06afd55324816ef18fb1f" +dependencies = [ + "arrayvec", + "bytes", + "chrono", + "const-hex", + "elliptic-curve", + "ethabi", + "generic-array", + "k256", + "num_enum", + "open-fastrlp", + "rand 0.8.5", + "rlp", + "serde", + "serde_json", + "strum", + "tempfile", + "thiserror", + "tiny-keccak", + "unicode-xid", +] + +[[package]] +name = "ethers-providers" +version = "2.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6434c9a33891f1effc9c75472e12666db2fa5a0fec4b29af6221680a6fe83ab2" +dependencies = [ + "async-trait", + "auto_impl", + "base64 0.21.7", + "bytes", + "const-hex", + "enr 0.10.0", + "ethers-core", + "futures-channel", + "futures-core", + "futures-timer", + "futures-util", + "hashers", + "http 0.2.12", + "instant", + "jsonwebtoken 8.3.0", + "once_cell", + "pin-project", + "reqwest 0.11.27", + "serde", + "serde_json", + "thiserror", + "tokio", + "tokio-tungstenite", + "tracing", + "tracing-futures", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "ws_stream_wasm", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -3125,6 +3240,21 @@ 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", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -3282,7 +3412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" dependencies = [ "gloo-timers", - "send_wrapper", + "send_wrapper 0.4.0", ] [[package]] @@ -3309,6 +3439,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -3484,6 +3623,15 @@ dependencies = [ "serde", ] +[[package]] +name = "hashers" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" +dependencies = [ + "fxhash", +] + [[package]] name = "hashlink" version = "0.8.4" @@ -3810,6 +3958,22 @@ dependencies = [ "tracing", ] +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.3" @@ -4358,7 +4522,7 @@ dependencies = [ "tokio-util", "tracing", "url", - "webpki-roots", + "webpki-roots 0.26.1", ] [[package]] @@ -5188,6 +5352,24 @@ dependencies = [ "unsigned-varint 0.7.2", ] +[[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 = "network" version = "0.0.0" @@ -5443,12 +5625,75 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "open-fastrlp" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" +dependencies = [ + "arrayvec", + "auto_impl", + "bytes", + "ethereum-types", + "open-fastrlp-derive", +] + +[[package]] +name = "open-fastrlp-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" +dependencies = [ + "bytes", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "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.63", +] + [[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.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "option-ext" version = "0.2.0" @@ -5626,6 +5871,16 @@ dependencies = [ "wyhash", ] +[[package]] +name = "pharos" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +dependencies = [ + "futures", + "rustc_version 0.4.0", +] + [[package]] name = "phf" version = "0.11.2" @@ -5889,6 +6144,7 @@ dependencies = [ "impl-codec", "impl-rlp", "impl-serde", + "scale-info", "uint", ] @@ -6304,6 +6560,7 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", + "hyper-rustls 0.24.2", "ipnet", "js-sys", "log", @@ -6311,12 +6568,15 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", + "rustls 0.21.12", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", "sync_wrapper", "system-configuration", "tokio", + "tokio-rustls 0.24.1", "tokio-util", "tower-service", "url", @@ -6324,6 +6584,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots 0.25.4", "winreg 0.50.0", ] @@ -6342,11 +6603,13 @@ dependencies = [ "http-body-util", "hyper 1.3.1", "hyper-rustls 0.26.0", + "hyper-tls", "hyper-util", "ipnet", "js-sys", "log", "mime", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -6359,13 +6622,14 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-native-tls", "tokio-rustls 0.25.0", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "webpki-roots", + "webpki-roots 0.26.1", "winreg 0.52.0", ] @@ -6685,7 +6949,7 @@ dependencies = [ "alloy-rlp", "assert_matches", "discv5", - "enr", + "enr 0.12.0", "generic-array", "parking_lot 0.12.2", "rand 0.8.5", @@ -6709,7 +6973,7 @@ dependencies = [ "alloy-rlp", "derive_more", "discv5", - "enr", + "enr 0.12.0", "futures", "itertools 0.12.1", "libp2p-identity", @@ -6732,7 +6996,7 @@ version = "0.2.0-beta.7" dependencies = [ "alloy-rlp", "data-encoding", - "enr", + "enr 0.12.0", "linked_hash_set", "parking_lot 0.12.2", "rand 0.8.5", @@ -7169,7 +7433,7 @@ dependencies = [ "criterion", "derive_more", "discv5", - "enr", + "enr 0.12.0", "fnv", "futures", "futures-test", @@ -7218,7 +7482,7 @@ dependencies = [ name = "reth-network-api" version = "0.2.0-beta.7" dependencies = [ - "enr", + "enr 0.12.0", "reth-discv4", "reth-eth-wire", "reth-network-types", @@ -7235,7 +7499,7 @@ version = "0.2.0-beta.7" dependencies = [ "alloy-primitives", "alloy-rlp", - "enr", + "enr 0.12.0", "rand 0.8.5", "secp256k1 0.28.2", "serde_json", @@ -8235,9 +8499,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" dependencies = [ "bytes", + "rlp-derive", "rustc-hex", ] +[[package]] +name = "rlp-derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "roaring" version = "0.10.4" @@ -8702,6 +8978,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" + [[package]] name = "serde" version = "1.0.201" @@ -9614,6 +9896,16 @@ dependencies = [ "syn 2.0.63", ] +[[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" @@ -9647,6 +9939,21 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "tokio-tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c" +dependencies = [ + "futures-util", + "log", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", + "tungstenite", + "webpki-roots 0.25.4", +] + [[package]] name = "tokio-util" version = "0.7.11" @@ -10013,6 +10320,26 @@ dependencies = [ "toml", ] +[[package]] +name = "tungstenite" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 0.2.12", + "httparse", + "log", + "rand 0.8.5", + "rustls 0.21.12", + "sha1", + "thiserror", + "url", + "utf-8", +] + [[package]] name = "txpool-tracing" version = "0.0.0" @@ -10096,6 +10423,12 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + [[package]] name = "universal-hash" version = "0.4.0" @@ -10142,6 +10475,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf16_iter" version = "1.0.5" @@ -10342,6 +10681,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + [[package]] name = "webpki-roots" version = "0.26.1" @@ -10608,6 +10953,25 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dad7bb64b8ef9c0aa27b6da38b452b0ee9fd82beaf276a87dd796fb55cbae14e" +[[package]] +name = "ws_stream_wasm" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7999f5f4217fe3818726b66257a4475f71e74ffd190776ad053fa159e50737f5" +dependencies = [ + "async_io_stream", + "futures", + "js-sys", + "log", + "pharos", + "rustc_version 0.4.0", + "send_wrapper 0.6.0", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wyhash" version = "0.5.0" @@ -10754,6 +11118,8 @@ version = "0.2.0-beta.7" dependencies = [ "alloy-provider", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=f1d7085)", + "alloy-transport-http", + "ethers-providers", "eyre", "reth-consensus", "reth-evm", diff --git a/Cargo.toml b/Cargo.toml index a7abd49e9dc1..677f4ff0394b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -301,13 +301,14 @@ alloy-rpc-types-beacon = { git = "https://github.com/alloy-rs/alloy", rev = "f1d alloy-genesis = { git = "https://github.com/alloy-rs/alloy", rev = "f1d7085" } alloy-node-bindings = { git = "https://github.com/alloy-rs/alloy", rev = "f1d7085" } alloy-provider = { git = "https://github.com/alloy-rs/alloy", rev = "f1d7085", default-features = false, features = [ - "reqwest", + "reqwest" ] } alloy-eips = { git = "https://github.com/alloy-rs/alloy", default-features = false, rev = "f1d7085" } alloy-signer = { git = "https://github.com/alloy-rs/alloy", rev = "f1d7085" } alloy-signer-wallet = { git = "https://github.com/alloy-rs/alloy", rev = "f1d7085" } alloy-network = { git = "https://github.com/alloy-rs/alloy", rev = "f1d7085" } alloy-consensus = { git = "https://github.com/alloy-rs/alloy", rev = "f1d7085" } +alloy-transport-http = { git = "https://github.com/alloy-rs/alloy", rev = "f1d7085" } # misc auto_impl = "1" diff --git a/testing/zkvm-script/Cargo.toml b/testing/zkvm-script/Cargo.toml index aa85516065f5..6d1aa0cdf165 100644 --- a/testing/zkvm-script/Cargo.toml +++ b/testing/zkvm-script/Cargo.toml @@ -18,7 +18,8 @@ reth-interfaces = { path = "../../crates/interfaces", default-features = false } reth-evm.workspace = true revm.workspace = true alloy-rpc-types.workspace = true -alloy-provider.workspace = true +alloy-provider = { workspace = true, features = ["reqwest"] } +alloy-transport-http.workspace = true url.workspace = true reth-revm.workspace = true reth-provider.workspace = true @@ -27,4 +28,5 @@ revm-primitives.workspace = true eyre.workspace = true serde_json.workspace = true reth-trie.workspace = true -tokio.workspace = true \ No newline at end of file +tokio.workspace = true +ethers-providers = "2.0.14" diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index c099179c3c4c..563ea9a23d8f 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -5,14 +5,45 @@ mod witness; use crate::{provider_db::RpcDb, witness::WitnessDb}; use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse}; +use ethers_providers::{Http, Middleware, Provider}; use eyre::Ok; use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; use reth_interfaces::executor::BlockValidationError; -use reth_primitives::{Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET}; +use reth_primitives::{ + trie::{AccountProof, StorageProof}, + Account, Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET, +}; use reth_provider::{BundleStateWithReceipts, ProviderError}; +use revm::db::CacheDB; use revm_primitives::U256; use url::Url; +fn convert_proof(proof: EIP1186AccountProofResponse) -> AccountProof { + let address = proof.address; + let balance = proof.balance; + let code_hash = proof.code_hash; + let nonce = proof.nonce.as_limbs()[0]; + let storage_hash = proof.storage_hash; + let account_proof = proof.account_proof; + let account_info = Account { nonce, balance, bytecode_hash: code_hash.into() }; + let storage_proofs = proof.storage_proof.into_iter().map(|storage_proof| { + let key = storage_proof.key; + let value = storage_proof.value; + let proof = storage_proof.proof; + let mut sp = StorageProof::new(key.0.into()); + sp.set_value(value); + sp.set_proof(proof); + sp + }); + AccountProof { + address, + info: Some(account_info), + proof: account_proof, + storage_root: storage_hash.into(), + storage_proofs: storage_proofs.collect(), + } +} + /// A struct that holds the input for a zkVM program to execute a block. pub struct SP1Input { /// The block that will be executed inside the zkVM program. @@ -25,20 +56,29 @@ pub struct SP1Input { async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { // We put imports here that are not used in the zkVM program. - use alloy_provider::{Provider, ReqwestProvider}; + use alloy_provider::{Provider as AlloyProvider, ReqwestProvider}; use reth_revm::database::StateProviderDatabase; - let merkle_block_td = U256::from(0); - // Initialize a provider. + println!("Initializing provider with URL: {}", rpc_url); + let ethers_provider = Provider::::try_from( + "https://eth-mainnet.g.alchemy.com/v2/hIxcf_hqT9It2hS8iCFeHKklL8tNyXNF", + ) + .expect("could not instantiate HTTP Provider"); + let provider = ReqwestProvider::new_http(rpc_url); + let merkle_block_td = U256::ZERO; + // provider.header_td_by_number(block_number)?.unwrap_or_default(); let alloy_block = provider - .get_block_by_number(block_number.into(), false) + .get_block_by_number(block_number.into(), true) .await? .ok_or(eyre::eyre!("block not found"))?; let block = RethBlock::try_from(alloy_block)?; + for transaction in &block.body { + println!("Transaction: {:?}", transaction); + } let chain_spec = ChainSpecBuilder::default() .chain(MAINNET.chain) @@ -48,10 +88,11 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { )) .unwrap(), ) - .cancun_activated() + .shanghai_activated() .build(); - let provider_db = RpcDb { provider: provider.clone(), block: block_number.into() }; - let db = StateProviderDatabase::new(provider_db); + let provider_db = RpcDb::new(provider.clone(), (block_number - 1).into()); + let db = CacheDB::new(provider_db); + println!("Instantiating executor"); let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()).executor(db); let BlockExecutionOutput { state, receipts, .. } = executor.execute( @@ -127,8 +168,11 @@ fn verify_stf(sp1_input: SP1Input) -> eyre::Result<()> { #[tokio::main] async fn main() { - let block_number = 1000u64; - let rpc_url = Url::parse("https://example.net").expect("Invalid RPC URL"); + let block_number = 18884920u64; + let rpc_url = + Url::parse("https://eth-mainnet.g.alchemy.com/v2/hIxcf_hqT9It2hS8iCFeHKklL8tNyXNF") + .expect("Invalid RPC URL"); + println!("Fetching block number {} from {}", block_number, rpc_url); // Get the input. let sp1_input = get_input(block_number, rpc_url).await.expect("Failed to get input"); // Verify the STF. diff --git a/testing/zkvm-script/src/provider_db.rs b/testing/zkvm-script/src/provider_db.rs index 5e9bfc0396a0..4c4f27660313 100644 --- a/testing/zkvm-script/src/provider_db.rs +++ b/testing/zkvm-script/src/provider_db.rs @@ -1,68 +1,98 @@ +use core::hash; + +use crate::convert_proof; #[allow(unused_imports)] use alloy_provider::{Provider, ReqwestProvider}; +use alloy_rpc_types::serde_helpers::num; use reth_interfaces::provider::ProviderResult; use reth_primitives::{ - trie::AccountProof, Account, Address, BlockId, BlockNumber, Bytecode, StorageKey, StorageValue, - B256, + trie::AccountProof, Account, Address, BlockId, BlockNumber, StorageKey, StorageValue, B256, + U256, U64, +}; +use reth_provider::{ + AccountReader, BlockHashReader, ProviderError, StateProvider, StateRootProvider, }; -use reth_provider::{AccountReader, BlockHashReader, StateProvider, StateRootProvider}; use reth_trie::updates::TrieUpdates; +use revm::DatabaseRef; +use revm_primitives::{result, AccountInfo, Bytecode, HashMap}; +use tokio::{runtime::Handle, task::block_in_place}; pub struct RpcDb { // TODO: make this a general "Provider" trait from alloy_provider. pub provider: ReqwestProvider, pub block: BlockId, + pub handle: Handle, } -impl StateProvider for RpcDb { - fn storage( - &self, - account: Address, - storage_key: StorageKey, - ) -> ProviderResult> { - todo!(); - } - - /// Get account code by its hash - fn bytecode_by_hash(&self, code_hash: B256) -> ProviderResult> { - unimplemented!(); - } - - /// Get account and storage proofs. - fn proof(&self, address: Address, keys: &[B256]) -> ProviderResult { - todo!(); +impl RpcDb { + pub fn new(provider: ReqwestProvider, block: BlockId) -> Self { + let handle = Handle::current(); + RpcDb { provider, block, handle } } } -impl BlockHashReader for RpcDb { - fn block_hash(&self, number: BlockNumber) -> ProviderResult> { - todo!(); - } +impl DatabaseRef for RpcDb { + type Error = ProviderError; - fn canonical_hashes_range( - &self, - start: BlockNumber, - end: BlockNumber, - ) -> reth_interfaces::provider::ProviderResult> { - todo!(); + fn basic_ref(&self, address: Address) -> Result, Self::Error> { + println!("getting account {}", address); + let result = block_in_place(|| { + Handle::current() + .block_on(async move { self.provider.get_proof(address, vec![], self.block).await }) + }); + let code = block_in_place(|| { + Handle::current() + .block_on(async move { self.provider.get_code_at(address, self.block).await }) + }); + result + .map(|proof| { + println!("address {}, nonce: {}", address, proof.nonce.as_limbs()[0]); + Some(AccountInfo { + nonce: proof.nonce.as_limbs()[0], + balance: proof.balance, + code_hash: proof.code_hash, + code: code.ok().map(|code| Bytecode::new_raw(code)), + }) + }) + .map_err(|err| ProviderError::FsPathError("hi".into())) } -} -impl AccountReader for RpcDb { - fn basic_account(&self, address: Address) -> ProviderResult> { - todo!(); + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + // We use basic_ref to get the code from the provider. + unimplemented!() } -} -impl StateRootProvider for RpcDb { - fn state_root(&self, bundle_state: &revm::db::BundleState) -> ProviderResult { - todo!(); + fn storage_ref(&self, address: Address, index: U256) -> Result { + println!("getting address {} {}", address, index); + let result = block_in_place(|| { + Handle::current().block_on(async move { + // TODO: this index might need to be hashed, not sure. + self.provider.get_storage_at(address, index.into(), self.block).await + }) + }); + result.map(|value| value.into()).map_err(|err| ProviderError::FsPathError("hi".into())) } - fn state_root_with_updates( - &self, - bundle_state: &revm::db::BundleState, - ) -> reth_interfaces::provider::ProviderResult<(B256, TrieUpdates)> { - todo!(); + fn block_hash_ref(&self, number: U256) -> Result { + println!("getting block_hash {:?}", number); + let num_u64 = number.as_limbs()[0]; + let result = block_in_place(|| { + Handle::current().block_on(async move { + self.provider.get_block_by_number(num_u64.into(), false).await + }) + }); + if result.is_err() { + return Err(ProviderError::FsPathError("hi".into())); + } + let block = result.unwrap(); + if block.is_none() { + return Err(ProviderError::FsPathError("hi".into())); + } + let block = block.unwrap(); + let hash = block.header.hash; + if hash.is_none() { + return Err(ProviderError::FsPathError("hi".into())); + } + Ok(hash.unwrap().into()) } } From 836f7d50f1b619deaf5f9b25e28577ca80c34a2d Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Sun, 19 May 2024 17:37:15 -0700 Subject: [PATCH 23/30] Cleanup --- Cargo.lock | 209 ++++++++++++++++++++++++- crates/primitives/src/alloy_compat.rs | 10 +- testing/zkvm-script/Cargo.toml | 2 + testing/zkvm-script/src/main.rs | 87 +++++++--- testing/zkvm-script/src/provider_db.rs | 199 +++++++++++++++-------- testing/zkvm-script/src/witness.rs | 173 ++++++++++++++++---- 6 files changed, 558 insertions(+), 122 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 861d4f1fb631..5d101e5be8ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -325,7 +325,7 @@ dependencies = [ "alloy-rpc-client", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=f1d7085)", "alloy-rpc-types-trace", - "alloy-transport", + "alloy-transport 0.1.0", "alloy-transport-http", "async-stream", "async-trait", @@ -369,7 +369,7 @@ version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=f1d7085#f1d708522e7fe676a3ee86dd198f87182f220927" dependencies = [ "alloy-json-rpc", - "alloy-transport", + "alloy-transport 0.1.0", "alloy-transport-http", "futures", "pin-project", @@ -585,6 +585,12 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-transport" +version = "0.0.0-reserved" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a5b50df399770969be46bb92a566ef1b3709d24778fa3d6b4312446facc72c" + [[package]] name = "alloy-transport" version = "0.1.0" @@ -609,7 +615,7 @@ version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=f1d7085#f1d708522e7fe676a3ee86dd198f87182f220927" dependencies = [ "alloy-json-rpc", - "alloy-transport", + "alloy-transport 0.1.0", "reqwest 0.12.4", "serde_json", "tower", @@ -924,6 +930,82 @@ dependencies = [ "zstd-safe", ] +[[package]] +name = "async-executor" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand 2.1.0", + "futures-lite 2.3.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.2.1", + "async-executor", + "async-io 2.3.2", + "async-lock 3.3.0", + "blocking", + "futures-lite 2.3.0", + "once_cell", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +dependencies = [ + "async-lock 3.3.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.7.0", + "rustix 0.38.34", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + [[package]] name = "async-lock" version = "3.3.0" @@ -949,6 +1031,32 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io 1.13.0", + "async-lock 2.8.0", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 1.13.0", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + [[package]] name = "async-stream" version = "0.3.5" @@ -1260,7 +1368,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "495f7104e962b7356f0aeb34247aca1fe7d2e783b346582db7f2904cb5717e88" dependencies = [ "async-channel 2.2.1", - "async-lock", + "async-lock 3.3.0", "async-task", "futures-io", "futures-lite 2.3.0", @@ -3361,7 +3469,10 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ + "fastrand 2.1.0", "futures-core", + "futures-io", + "parking", "pin-project-lite", ] @@ -4396,6 +4507,17 @@ dependencies = [ "memoffset", ] +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "ipconfig" version = "0.3.2" @@ -4707,6 +4829,15 @@ dependencies = [ "sha3-asm", ] +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -4975,6 +5106,12 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -5002,6 +5139,9 @@ name = "log" version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +dependencies = [ + "value-bag", +] [[package]] name = "lru" @@ -6025,6 +6165,37 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 0.38.34", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "pollster" version = "0.3.0" @@ -6202,7 +6373,7 @@ dependencies = [ "hex", "lazy_static", "procfs-core", - "rustix", + "rustix 0.38.34", ] [[package]] @@ -8634,6 +8805,20 @@ dependencies = [ "semver 1.0.23", ] +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + [[package]] name = "rustix" version = "0.38.34" @@ -8643,7 +8828,7 @@ dependencies = [ "bitflags 2.5.0", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.13", "windows-sys 0.52.0", ] @@ -9636,7 +9821,7 @@ checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand 2.1.0", - "rustix", + "rustix 0.38.34", "windows-sys 0.52.0", ] @@ -10514,6 +10699,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "value-bag" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a84c137d37ab0142f0f2ddfe332651fdbf252e7b7dbb4e67b6c1f1b2e925101" + [[package]] name = "vcpkg" version = "0.2.15" @@ -10705,7 +10896,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.34", ] [[package]] @@ -11118,7 +11309,9 @@ version = "0.2.0-beta.7" dependencies = [ "alloy-provider", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=f1d7085)", + "alloy-transport 0.0.0-reserved", "alloy-transport-http", + "async-std", "ethers-providers", "eyre", "reth-consensus", diff --git a/crates/primitives/src/alloy_compat.rs b/crates/primitives/src/alloy_compat.rs index 8b4368a1211b..0ca849c5dd9f 100644 --- a/crates/primitives/src/alloy_compat.rs +++ b/crates/primitives/src/alloy_compat.rs @@ -2,10 +2,11 @@ use crate::{ Block, Header, Transaction, TransactionSigned, TxEip1559, TxEip2930, TxEip4844, TxLegacy, - TxType, + TxType, U256, }; use alloy_primitives::TxKind; use alloy_rlp::Error as RlpError; +use alloy_rpc_types::Parity; impl TryFrom for Block { type Error = alloy_rpc_types::ConversionError; @@ -21,6 +22,11 @@ impl TryFrom for Block { .into_iter() .map(|tx| { let signature = tx.signature.ok_or(ConversionError::MissingSignature)?; + let recovery_id = if signature.v > U256::from(1) { + signature.v - U256::from(37) + } else { + signature.v + }; Ok(TransactionSigned::from_transaction_and_signature( tx.try_into()?, crate::Signature { @@ -28,7 +34,7 @@ impl TryFrom for Block { s: signature.s, odd_y_parity: signature .y_parity - .unwrap_or(alloy_rpc_types::Parity(false)) + .unwrap_or(Parity(recovery_id == U256::from(1))) .0, }, )) diff --git a/testing/zkvm-script/Cargo.toml b/testing/zkvm-script/Cargo.toml index 6d1aa0cdf165..1cfd2fb34c37 100644 --- a/testing/zkvm-script/Cargo.toml +++ b/testing/zkvm-script/Cargo.toml @@ -30,3 +30,5 @@ serde_json.workspace = true reth-trie.workspace = true tokio.workspace = true ethers-providers = "2.0.14" +alloy-transport = "0.0.0-reserved" +async-std = "1.12.0" diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index 563ea9a23d8f..822d32bb5656 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -1,8 +1,11 @@ //! A simple script that has takes in a block & RPC, fetches the block. -mod provider_db; -mod witness; +pub mod provider_db; +pub mod witness; -use crate::{provider_db::RpcDb, witness::WitnessDb}; +use crate::{ + provider_db::RpcDb, + witness::{CheckDb, WitnessDb}, +}; use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse}; use ethers_providers::{Http, Middleware, Provider}; @@ -11,11 +14,11 @@ use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; use reth_interfaces::executor::BlockValidationError; use reth_primitives::{ trie::{AccountProof, StorageProof}, - Account, Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET, + Account, Address, Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET, }; use reth_provider::{BundleStateWithReceipts, ProviderError}; -use revm::db::CacheDB; -use revm_primitives::U256; +use revm::{db::CacheDB, Database}; +use revm_primitives::{AccountInfo, HashMap, U256}; use url::Url; fn convert_proof(proof: EIP1186AccountProofResponse) -> AccountProof { @@ -44,28 +47,22 @@ fn convert_proof(proof: EIP1186AccountProofResponse) -> AccountProof { } } +#[derive(Debug, Clone)] /// A struct that holds the input for a zkVM program to execute a block. pub struct SP1Input { /// The block that will be executed inside the zkVM program. pub block: RethBlock, - /// Used forinitializing the WitnessDB inside the zkVM program. - pub merkle_proofs: Vec, - /// A vector of contract bytecode of the same length as [`merkle_proofs`]. - pub code: Vec>, + /// Address to merkle proofs. + pub address_to_proof: HashMap, + /// Block number to block hash. + pub block_hashes: HashMap, } async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { // We put imports here that are not used in the zkVM program. use alloy_provider::{Provider as AlloyProvider, ReqwestProvider}; - use reth_revm::database::StateProviderDatabase; // Initialize a provider. - println!("Initializing provider with URL: {}", rpc_url); - let ethers_provider = Provider::::try_from( - "https://eth-mainnet.g.alchemy.com/v2/hIxcf_hqT9It2hS8iCFeHKklL8tNyXNF", - ) - .expect("could not instantiate HTTP Provider"); - let provider = ReqwestProvider::new_http(rpc_url); let merkle_block_td = U256::ZERO; // provider.header_td_by_number(block_number)?.unwrap_or_default(); @@ -91,7 +88,9 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { .shanghai_activated() .build(); let provider_db = RpcDb::new(provider.clone(), (block_number - 1).into()); - let db = CacheDB::new(provider_db); + // The reason we can clone the provider_db is all the stateful elements are within Arcs. + let db = CacheDB::new(provider_db.clone()); + println!("Instantiating executor"); let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()).executor(db); @@ -110,6 +109,7 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { Receipts::from_block_receipt(receipts), block.header.number, ); + println!("Done processing block!"); let next_block = provider .get_block_by_number((block_number + 1).into(), false) @@ -122,8 +122,43 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { // block_state.hash_state_slow().state_root_with_updates(provider.tx_ref())?; // TODO: check that the computed state_root matches the next_block.header.state_root - let sp1_input = SP1Input { block: block.clone(), merkle_proofs: vec![], code: vec![] }; - Ok(sp1_input) + let sp1_input = provider_db.get_sp1_input(&block).await; + + // println!("Got address_to_storage: {:?}", address_to_storage); + + // let sp1_input = SP1Input { + // block: block.clone(), + // merkle_proofs: merkle_proofs.clone(), + // address_to_account_info: provider_db.address_to_account_info.read().unwrap().clone(), + // address_to_storage: address_to_storage.clone(), + // block_hashes: provider_db.block_hashes.read().unwrap().clone(), + // code: code.clone(), + // }; + + // Now we do the check + let witness_db_inner = WitnessDb::new(sp1_input.clone()); + let witness_db = CacheDB::new(witness_db_inner); + + // let address: Address = "0xCb2286d9471cc185281c4f763d34A962ED212962".parse().unwrap(); + // let index = U256::from(7); + // let result = witness_db.storage(address, index); + + // let check_db = CheckDb { witness: witness_db, rpc: db }; + + let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) + .executor(witness_db); + let BlockExecutionOutput { state, receipts, .. } = executor.execute( + ( + &block + .clone() + .with_recovered_senders() + .ok_or(BlockValidationError::SenderRecoveryError)?, + (merkle_block_td + block.header.difficulty).into(), + ) + .into(), + )?; + + Ok(sp1_input.clone()) } /// Program that verifies the STF, run inside the zkVM. @@ -136,12 +171,18 @@ fn verify_stf(sp1_input: SP1Input) -> eyre::Result<()> { )) .unwrap(), ) - .cancun_activated() + .shanghai_activated() .build(); let block = sp1_input.block.clone(); let merkle_block_td = U256::from(0); // TODO: this should be an input? - let witness_db = WitnessDb::new(sp1_input.block.header.state_root, sp1_input.merkle_proofs); + let witness_db_inner = WitnessDb::new(sp1_input.clone()); + let witness_db = CacheDB::new(witness_db_inner); + + // let provider_db = RpcDb::new(provider.clone(), (block_number - 1).into()); + // let db = CacheDB::new(provider_db.clone()); + // let check_db = + // witness_db::CheckDb { witness: witness_db.clone(), rpc: RpcDb::new(provider_db) }; // TODO: can we import `EthExecutorProvider` from reth-evm instead of reth-node-ethereum? let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) @@ -168,7 +209,7 @@ fn verify_stf(sp1_input: SP1Input) -> eyre::Result<()> { #[tokio::main] async fn main() { - let block_number = 18884920u64; + let block_number = 18884864u64; let rpc_url = Url::parse("https://eth-mainnet.g.alchemy.com/v2/hIxcf_hqT9It2hS8iCFeHKklL8tNyXNF") .expect("Invalid RPC URL"); diff --git a/testing/zkvm-script/src/provider_db.rs b/testing/zkvm-script/src/provider_db.rs index 4c4f27660313..a41ba4d7c05b 100644 --- a/testing/zkvm-script/src/provider_db.rs +++ b/testing/zkvm-script/src/provider_db.rs @@ -1,33 +1,154 @@ -use core::hash; - -use crate::convert_proof; #[allow(unused_imports)] use alloy_provider::{Provider, ReqwestProvider}; -use alloy_rpc_types::serde_helpers::num; -use reth_interfaces::provider::ProviderResult; +use alloy_rpc_types::{BlockId, EIP1186AccountProofResponse}; +use async_std::task; +use futures::future::join_all; + +// use alloy_transport::TransportResult; +use crate::RethBlock; +use alloy_transport_http::ReqwestTransport; use reth_primitives::{ - trie::AccountProof, Account, Address, BlockId, BlockNumber, StorageKey, StorageValue, B256, - U256, U64, + trie::AccountProof, Account, Address, BlockNumber, StorageKey, StorageValue, B256, U256, U64, }; use reth_provider::{ AccountReader, BlockHashReader, ProviderError, StateProvider, StateRootProvider, }; +use reth_revm::DatabaseRef; use reth_trie::updates::TrieUpdates; -use revm::DatabaseRef; -use revm_primitives::{result, AccountInfo, Bytecode, HashMap}; +use revm_primitives::{result, AccountInfo, Bytecode, HashMap, HashSet}; +use std::{ + hash::Hash, + sync::{Arc, RwLock}, +}; use tokio::{runtime::Handle, task::block_in_place}; +use crate::SP1Input; + +#[derive(Clone, Debug)] +/// An implementation of a [`DatabaseRef`] that uses an [`ReqwestProvider`] to fetch data. pub struct RpcDb { - // TODO: make this a general "Provider" trait from alloy_provider. + /// The [`ReqwestProvider`] that will be used to fetch data. + /// TODO: In the future this should be a generic [`Provider`] trait from alloy_provider. pub provider: ReqwestProvider, + /// The [`BlockId`] that will be used when fetching data from the RPC. pub block: BlockId, - pub handle: Handle, + + /// A mapping from [`Address`] to [`AccountInfo`] for all addresses that have been fetched. + pub address_to_account_info: Arc>>, + pub address_to_storage: Arc>>>, + pub block_hashes: Arc>>, } impl RpcDb { pub fn new(provider: ReqwestProvider, block: BlockId) -> Self { - let handle = Handle::current(); - RpcDb { provider, block, handle } + RpcDb { + provider, + block, + address_to_account_info: Arc::new(RwLock::new(HashMap::new())), + address_to_storage: Arc::new(RwLock::new(HashMap::new())), + block_hashes: Arc::new(RwLock::new(HashMap::new())), + } + } + + /// Fetch the account info (and code) for an address. + async fn fetch_account_info(&self, address: Address) -> AccountInfo { + // TODO: when alloy adds a `eth_getAccount` method, we can use that here to save RPC load, + // since getProof is expensive. + let proof = self + .provider + .get_proof(address, vec![], self.block) + .await + .expect("Failed to get proof"); + let code = + self.provider.get_code_at(address, self.block).await.expect("Failed to get code"); + let bytecode = Bytecode::new_raw(code); + + let account_info = AccountInfo { + nonce: proof.nonce.as_limbs()[0], + balance: proof.balance, + code_hash: proof.code_hash, + code: Some(bytecode.clone()), + }; + + // Keep track of the account_info and code in the mappings for RpcDb. + self.address_to_account_info.write().unwrap().insert(address, account_info.clone()); + + account_info + } + + /// Fetch the storage for an address and index. + async fn fetch_storage(&self, address: Address, index: U256) -> U256 { + let value = self + .provider + .get_storage_at(address, index, self.block) + .await + .expect("Failed to get storage"); + self.address_to_storage + .write() + .unwrap() + .entry(address) + .or_insert_with(HashMap::new) + .insert(index, value); + value + } + + /// Fetch the block hash for a block number. + async fn fetch_block_hash(&self, number: U256) -> B256 { + let num_u64 = number.as_limbs()[0]; + let block = self + .provider + .get_block_by_number(num_u64.into(), false) + .await + .expect("Failed to get block"); + let hash = block.expect("Block not found").header.hash.expect("Block hash not found"); + self.block_hashes.write().unwrap().insert(number, hash); + hash + } + + /// Given all of the account and storage accesses in a block, fetch merkle proofs for all of + /// them. + async fn get_proofs(&self) -> HashMap { + // Acquire read locks at the top + let account_info = self.address_to_account_info.read().unwrap(); + let storage_guard = self.address_to_storage.read().unwrap(); + + let mut addresses: HashSet<&Address> = account_info.keys().collect(); + addresses.extend(storage_guard.keys()); + + // Create a future for each address to fetch a proof of the account and storage keys. + let futures: Vec<_> = addresses + .into_iter() + .map(|address| { + let storage_keys: Vec = storage_guard + .get(address) + .map(|storage_map| { + storage_map.keys().into_iter().map(|k| (*k).into()).collect() + }) + .unwrap_or_else(Vec::new); + + let provider = self.provider.clone(); + let block = self.block; + + async move { + match provider.get_proof(*address, storage_keys, block).await { + Ok(proof) => Some((address, proof)), + Err(_) => None, + } + } + }) + .collect(); + + // Execute all futures in parallel. + let results = join_all(futures).await; + + // Collect results into a HashMap. + results.into_iter().filter_map(|result| result).collect() + } + + pub async fn get_sp1_input(&self, block: &RethBlock) -> SP1Input { + let proofs = self.get_proofs().await; + let block_hashes = self.block_hashes.read().unwrap().clone(); + SP1Input { block: block.clone(), address_to_proof: proofs, block_hashes } } } @@ -35,64 +156,18 @@ impl DatabaseRef for RpcDb { type Error = ProviderError; fn basic_ref(&self, address: Address) -> Result, Self::Error> { - println!("getting account {}", address); - let result = block_in_place(|| { - Handle::current() - .block_on(async move { self.provider.get_proof(address, vec![], self.block).await }) - }); - let code = block_in_place(|| { - Handle::current() - .block_on(async move { self.provider.get_code_at(address, self.block).await }) - }); - result - .map(|proof| { - println!("address {}, nonce: {}", address, proof.nonce.as_limbs()[0]); - Some(AccountInfo { - nonce: proof.nonce.as_limbs()[0], - balance: proof.balance, - code_hash: proof.code_hash, - code: code.ok().map(|code| Bytecode::new_raw(code)), - }) - }) - .map_err(|err| ProviderError::FsPathError("hi".into())) + Ok(Some(task::block_on(self.fetch_account_info(address)))) } fn code_by_hash_ref(&self, code_hash: B256) -> Result { - // We use basic_ref to get the code from the provider. unimplemented!() } fn storage_ref(&self, address: Address, index: U256) -> Result { - println!("getting address {} {}", address, index); - let result = block_in_place(|| { - Handle::current().block_on(async move { - // TODO: this index might need to be hashed, not sure. - self.provider.get_storage_at(address, index.into(), self.block).await - }) - }); - result.map(|value| value.into()).map_err(|err| ProviderError::FsPathError("hi".into())) + Ok(task::block_on(self.fetch_storage(address, index))) } fn block_hash_ref(&self, number: U256) -> Result { - println!("getting block_hash {:?}", number); - let num_u64 = number.as_limbs()[0]; - let result = block_in_place(|| { - Handle::current().block_on(async move { - self.provider.get_block_by_number(num_u64.into(), false).await - }) - }); - if result.is_err() { - return Err(ProviderError::FsPathError("hi".into())); - } - let block = result.unwrap(); - if block.is_none() { - return Err(ProviderError::FsPathError("hi".into())); - } - let block = block.unwrap(); - let hash = block.header.hash; - if hash.is_none() { - return Err(ProviderError::FsPathError("hi".into())); - } - Ok(hash.unwrap().into()) + Ok(task::block_on(self.fetch_block_hash(number))) } } diff --git a/testing/zkvm-script/src/witness.rs b/testing/zkvm-script/src/witness.rs index 72514b11a206..bd9856e4411f 100644 --- a/testing/zkvm-script/src/witness.rs +++ b/testing/zkvm-script/src/witness.rs @@ -2,54 +2,153 @@ use alloy_rpc_types::EIP1186AccountProofResponse; use reth_primitives::B256; // TODO: we need to be able to import `ProviderError` from `reth_provider` in the zkVM. use reth_provider::ProviderError; -use revm::{db::InMemoryDB, Database}; -use revm_primitives::AccountInfo; +use revm::{db::InMemoryDB, Database, DatabaseRef}; +use revm_primitives::{keccak256, AccountInfo, Address, Bytecode, HashMap, U256}; + +use crate::{provider_db::RpcDb, SP1Input}; +use revm::db::CacheDB; pub(crate) struct WitnessDb { pub(crate) inner: InMemoryDB, + pub address_to_account_info: HashMap, + pub address_to_storage: HashMap>, + pub block_hashes: HashMap, pub(crate) state_root: B256, } impl WitnessDb { - pub(crate) fn new(state_root: B256, merkle_proofs: Vec) -> Self { + pub(crate) fn new(sp1_input: SP1Input) -> Self { + println!("WitnessDb::new"); let mut inner = InMemoryDB::default(); - for proof in merkle_proofs { - // TODO: verify proof against state_root - // Note that we do not need to hash the code against the code_hash, since - // `insert_contract` already does this. - let address = proof.address; - let account_info = AccountInfo { - nonce: proof.nonce.as_limbs()[0], // Is there a better way to do U64 -> u64? - balance: proof.balance, - code_hash: proof.code_hash, - code: None, // TODO: fill this with code - }; - inner.insert_account_info(address, account_info); - for storage_proof in proof.storage_proof { - // TODO: verify storage proof. - let slot = storage_proof.key.0; - let value = storage_proof.value; - let _ = inner.insert_account_storage(address, slot.into(), value); - } + // let SP1Input { block, address_to_account_info, address_to_storage, block_hashes, .. } = + // sp1_input; + // for (proof, code) in merkle_proofs.into_iter().zip(code.into_iter()) { + // // TODO: verify proof against state_root + // // Note that we do not need to hash the code against the code_hash, since + // // `insert_contract` already does this. + // let address = proof.address; + // let code = if code.is_empty() { None } else { Some(Bytecode::new_raw(code.into())) }; + // let account_info = AccountInfo { + // nonce: proof.nonce.as_limbs()[0], // Is there a better way to do U64 -> u64? + // balance: proof.balance, + // code_hash: proof.code_hash, + // code, + // }; + // inner.insert_account_info(address, account_info); + // let storage_map = address_to_storage.get(&address); + // println!("inserting storage for address {}", address); + // if let Some(storage_map) = storage_map { + // for (index, value) in storage_map { + // println!("inserting storage {} {}", index, value); + // let _ = inner.insert_account_storage(address, *index, *value); + // } + // } + // // TODO: right now these are empty. + // // for storage_proof in proof.storage_proof { + // // // TODO: verify storage proof. + // // let slot = storage_proof.key.0; + // // let value = storage_proof.value; + // // let _ = inner.insert_account_storage(address, slot.into(), value); + // // } + // } + Self { + inner, + address_to_account_info: HashMap::new(), + address_to_storage: HashMap::new(), + block_hashes: HashMap::new(), + state_root: sp1_input.block.state_root, } - Self { inner, state_root } } } // TODO: is there some automatic way to implement this? // TODO: fix all the dummy ProviderError -impl Database for WitnessDb { +impl DatabaseRef for WitnessDb { + type Error = ProviderError; + + fn basic_ref( + &self, + address: revm_primitives::Address, + ) -> Result, Self::Error> { + Ok(self.address_to_account_info.get(&address).cloned()) + // self.inner.basic_ref(address).map_err(|_| ProviderError::UnsupportedProvider) + } + + fn code_by_hash_ref(&self, code_hash: B256) -> Result { + unimplemented!() + } + + fn storage_ref( + &self, + address: revm_primitives::Address, + index: U256, + ) -> Result { + Ok(self.address_to_storage.get(&address).unwrap().get(&index).unwrap().clone()) + // self.inner.storage_ref(address, index).map_err(|_| ProviderError::UnsupportedProvider) + } + + fn block_hash_ref(&self, number: U256) -> Result { + Ok(self.block_hashes.get(&number).unwrap().clone()) + // self.inner.block_hash_ref(number).map_err(|_| ProviderError::UnsupportedProvider) + } + + // fn bas( + // &mut self, + // address: revm_primitives::Address, + // ) -> Result, Self::Error> { + // self.inner.basic(address).map_err(|_| ProviderError::UnsupportedProvider) + // } + + // fn code_by_hash(&mut self, code_hash: B256) -> Result + // { self.inner.code_by_hash(code_hash).map_err(|_| ProviderError::UnsupportedProvider) + // } + + // fn storage( + // &mut self, + // address: revm_primitives::Address, + // index: revm_primitives::U256, + // ) -> Result { + // self.inner.storage(address, index).map_err(|_| ProviderError::UnsupportedProvider) + // } + + // fn block_hash(&mut self, number: revm_primitives::U256) -> Result { + // self.inner.block_hash(number).map_err(|_| ProviderError::UnsupportedProvider) + // } +} + +pub struct CheckDb { + pub witness: CacheDB, + pub rpc: CacheDB, +} + +impl Database for CheckDb { type Error = ProviderError; fn basic( &mut self, address: revm_primitives::Address, ) -> Result, Self::Error> { - self.inner.basic(address).map_err(|_| ProviderError::UnsupportedProvider) + let res1 = self.witness.basic(address).unwrap(); + let res2 = self.rpc.basic(address).unwrap(); + if res1 != res2 { + println!("basic mismatch for address {}", address); + println!("witness: {:?}", res1); + println!("rpc: {:?}", res2); + panic!("account mismatch"); + } + self.rpc.basic(address) } fn code_by_hash(&mut self, code_hash: B256) -> Result { - self.inner.code_by_hash(code_hash).map_err(|_| ProviderError::UnsupportedProvider) + let res1 = self.witness.code_by_hash(code_hash).unwrap(); + let res2 = self.rpc.code_by_hash(code_hash).unwrap(); + if res1 != res2 { + println!("code mismatch for hash {}", code_hash); + println!("witness: {:?}", res1); + println!("rpc: {:?}", res2); + panic!("code mismatch"); + } + self.rpc.code_by_hash(code_hash) } fn storage( @@ -57,10 +156,30 @@ impl Database for WitnessDb { address: revm_primitives::Address, index: revm_primitives::U256, ) -> Result { - self.inner.storage(address, index).map_err(|_| ProviderError::UnsupportedProvider) + let index_b = B256::from(index); + let hash = keccak256(index_b); + let hash_b: U256 = B256::from(hash).into(); + let res1 = self.witness.storage(address, hash_b).unwrap(); + let res2 = self.rpc.storage(address, index).unwrap(); + if res1 != res2 { + println!("storage mismatch for address {} index {}", address, index); + println!("witness: {:?}", res1); + println!("rpc: {:?}", res2); + } else { + println!("no storage mismatch for address {} index {}", address, index); + } + self.rpc.storage(address, index) } fn block_hash(&mut self, number: revm_primitives::U256) -> Result { - self.inner.block_hash(number).map_err(|_| ProviderError::UnsupportedProvider) + let res1 = self.witness.block_hash(number).unwrap(); + let res2 = self.rpc.block_hash(number).unwrap(); + if res1 != res2 { + println!("block hash mismatch for number {}", number); + println!("witness: {:?}", res1); + println!("rpc: {:?}", res2); + panic!("block_hash mismatch"); + } + self.rpc.block_hash(number) } } From 74d4f678873ef49886e2165b2ebf7847c412c777 Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Sun, 19 May 2024 17:39:24 -0700 Subject: [PATCH 24/30] Further clean --- testing/zkvm-script/src/witness.rs | 162 ++++++++++++----------------- 1 file changed, 67 insertions(+), 95 deletions(-) diff --git a/testing/zkvm-script/src/witness.rs b/testing/zkvm-script/src/witness.rs index bd9856e4411f..01d2284f63cc 100644 --- a/testing/zkvm-script/src/witness.rs +++ b/testing/zkvm-script/src/witness.rs @@ -61,8 +61,6 @@ impl WitnessDb { } } -// TODO: is there some automatic way to implement this? -// TODO: fix all the dummy ProviderError impl DatabaseRef for WitnessDb { type Error = ProviderError; @@ -71,7 +69,6 @@ impl DatabaseRef for WitnessDb { address: revm_primitives::Address, ) -> Result, Self::Error> { Ok(self.address_to_account_info.get(&address).cloned()) - // self.inner.basic_ref(address).map_err(|_| ProviderError::UnsupportedProvider) } fn code_by_hash_ref(&self, code_hash: B256) -> Result { @@ -84,102 +81,77 @@ impl DatabaseRef for WitnessDb { index: U256, ) -> Result { Ok(self.address_to_storage.get(&address).unwrap().get(&index).unwrap().clone()) - // self.inner.storage_ref(address, index).map_err(|_| ProviderError::UnsupportedProvider) } fn block_hash_ref(&self, number: U256) -> Result { Ok(self.block_hashes.get(&number).unwrap().clone()) - // self.inner.block_hash_ref(number).map_err(|_| ProviderError::UnsupportedProvider) } - - // fn bas( - // &mut self, - // address: revm_primitives::Address, - // ) -> Result, Self::Error> { - // self.inner.basic(address).map_err(|_| ProviderError::UnsupportedProvider) - // } - - // fn code_by_hash(&mut self, code_hash: B256) -> Result - // { self.inner.code_by_hash(code_hash).map_err(|_| ProviderError::UnsupportedProvider) - // } - - // fn storage( - // &mut self, - // address: revm_primitives::Address, - // index: revm_primitives::U256, - // ) -> Result { - // self.inner.storage(address, index).map_err(|_| ProviderError::UnsupportedProvider) - // } - - // fn block_hash(&mut self, number: revm_primitives::U256) -> Result { - // self.inner.block_hash(number).map_err(|_| ProviderError::UnsupportedProvider) - // } -} - -pub struct CheckDb { - pub witness: CacheDB, - pub rpc: CacheDB, } -impl Database for CheckDb { - type Error = ProviderError; - - fn basic( - &mut self, - address: revm_primitives::Address, - ) -> Result, Self::Error> { - let res1 = self.witness.basic(address).unwrap(); - let res2 = self.rpc.basic(address).unwrap(); - if res1 != res2 { - println!("basic mismatch for address {}", address); - println!("witness: {:?}", res1); - println!("rpc: {:?}", res2); - panic!("account mismatch"); - } - self.rpc.basic(address) - } - - fn code_by_hash(&mut self, code_hash: B256) -> Result { - let res1 = self.witness.code_by_hash(code_hash).unwrap(); - let res2 = self.rpc.code_by_hash(code_hash).unwrap(); - if res1 != res2 { - println!("code mismatch for hash {}", code_hash); - println!("witness: {:?}", res1); - println!("rpc: {:?}", res2); - panic!("code mismatch"); - } - self.rpc.code_by_hash(code_hash) - } - - fn storage( - &mut self, - address: revm_primitives::Address, - index: revm_primitives::U256, - ) -> Result { - let index_b = B256::from(index); - let hash = keccak256(index_b); - let hash_b: U256 = B256::from(hash).into(); - let res1 = self.witness.storage(address, hash_b).unwrap(); - let res2 = self.rpc.storage(address, index).unwrap(); - if res1 != res2 { - println!("storage mismatch for address {} index {}", address, index); - println!("witness: {:?}", res1); - println!("rpc: {:?}", res2); - } else { - println!("no storage mismatch for address {} index {}", address, index); - } - self.rpc.storage(address, index) - } - - fn block_hash(&mut self, number: revm_primitives::U256) -> Result { - let res1 = self.witness.block_hash(number).unwrap(); - let res2 = self.rpc.block_hash(number).unwrap(); - if res1 != res2 { - println!("block hash mismatch for number {}", number); - println!("witness: {:?}", res1); - println!("rpc: {:?}", res2); - panic!("block_hash mismatch"); - } - self.rpc.block_hash(number) - } -} +// pub struct CheckDb { +// pub witness: CacheDB, +// pub rpc: CacheDB, +// } + +// impl Database for CheckDb { +// type Error = ProviderError; + +// fn basic( +// &mut self, +// address: revm_primitives::Address, +// ) -> Result, Self::Error> { +// let res1 = self.witness.basic(address).unwrap(); +// let res2 = self.rpc.basic(address).unwrap(); +// if res1 != res2 { +// println!("basic mismatch for address {}", address); +// println!("witness: {:?}", res1); +// println!("rpc: {:?}", res2); +// panic!("account mismatch"); +// } +// self.rpc.basic(address) +// } + +// fn code_by_hash(&mut self, code_hash: B256) -> Result +// { let res1 = self.witness.code_by_hash(code_hash).unwrap(); +// let res2 = self.rpc.code_by_hash(code_hash).unwrap(); +// if res1 != res2 { +// println!("code mismatch for hash {}", code_hash); +// println!("witness: {:?}", res1); +// println!("rpc: {:?}", res2); +// panic!("code mismatch"); +// } +// self.rpc.code_by_hash(code_hash) +// } + +// fn storage( +// &mut self, +// address: revm_primitives::Address, +// index: revm_primitives::U256, +// ) -> Result { +// let index_b = B256::from(index); +// let hash = keccak256(index_b); +// let hash_b: U256 = B256::from(hash).into(); +// let res1 = self.witness.storage(address, hash_b).unwrap(); +// let res2 = self.rpc.storage(address, index).unwrap(); +// if res1 != res2 { +// println!("storage mismatch for address {} index {}", address, index); +// println!("witness: {:?}", res1); +// println!("rpc: {:?}", res2); +// } else { +// println!("no storage mismatch for address {} index {}", address, index); +// } +// self.rpc.storage(address, index) +// } + +// fn block_hash(&mut self, number: revm_primitives::U256) -> Result { +// let res1 = self.witness.block_hash(number).unwrap(); +// let res2 = self.rpc.block_hash(number).unwrap(); +// if res1 != res2 { +// println!("block hash mismatch for number {}", number); +// println!("witness: {:?}", res1); +// println!("rpc: {:?}", res2); +// panic!("block_hash mismatch"); +// } +// self.rpc.block_hash(number) +// } +// } From 592f92dbef5a7de8db5d22abf61ee03f757f59de Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Sun, 19 May 2024 17:50:26 -0700 Subject: [PATCH 25/30] cleanup --- testing/zkvm-script/src/main.rs | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index 822d32bb5656..e98bb9104de7 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -2,10 +2,7 @@ pub mod provider_db; pub mod witness; -use crate::{ - provider_db::RpcDb, - witness::{CheckDb, WitnessDb}, -}; +use crate::{provider_db::RpcDb, witness::WitnessDb}; use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse}; use ethers_providers::{Http, Middleware, Provider}; @@ -124,27 +121,10 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { let sp1_input = provider_db.get_sp1_input(&block).await; - // println!("Got address_to_storage: {:?}", address_to_storage); - - // let sp1_input = SP1Input { - // block: block.clone(), - // merkle_proofs: merkle_proofs.clone(), - // address_to_account_info: provider_db.address_to_account_info.read().unwrap().clone(), - // address_to_storage: address_to_storage.clone(), - // block_hashes: provider_db.block_hashes.read().unwrap().clone(), - // code: code.clone(), - // }; - - // Now we do the check + // This code will be the code that runs inside the zkVM. let witness_db_inner = WitnessDb::new(sp1_input.clone()); let witness_db = CacheDB::new(witness_db_inner); - // let address: Address = "0xCb2286d9471cc185281c4f763d34A962ED212962".parse().unwrap(); - // let index = U256::from(7); - // let result = witness_db.storage(address, index); - - // let check_db = CheckDb { witness: witness_db, rpc: db }; - let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) .executor(witness_db); let BlockExecutionOutput { state, receipts, .. } = executor.execute( From bdbd0febb2dbd6b6092f5d5d3550f6c13f60231e Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Sun, 19 May 2024 18:35:06 -0700 Subject: [PATCH 26/30] more cleanup --- Cargo.lock | 5 +- crates/primitives/src/chain/spec.rs | 4 +- testing/zkvm-script/src/main.rs | 48 ++++----- testing/zkvm-script/src/provider_db.rs | 46 ++++++++- testing/zkvm-script/src/witness.rs | 136 +++++-------------------- 5 files changed, 93 insertions(+), 146 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6c7d6573c6c9..bdd3bc9f31bf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -703,9 +703,9 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb28aa4ecd32fdfa1b1bdd111ff7357dd562c6b2372694cf9e613434fcba659" +checksum = "d55bd16fdb7ff4bd74cc4c878eeac7e8a27c0d7ba9df4ab58d9310aaafb62d43" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -717,7 +717,6 @@ dependencies = [ "proptest", "proptest-derive", "serde", - "smallvec", "tracing", ] diff --git a/crates/primitives/src/chain/spec.rs b/crates/primitives/src/chain/spec.rs index 98ec3d972dcc..0809aa3fa261 100644 --- a/crates/primitives/src/chain/spec.rs +++ b/crates/primitives/src/chain/spec.rs @@ -1024,7 +1024,7 @@ impl From for ChainSpec { let time_hardfork_opts = [ (Hardfork::Shanghai, genesis.config.shanghai_time), (Hardfork::Cancun, genesis.config.cancun_time), - (Hardfork::Prague, genesis.config.prague_time), + (Hardfork::Prague, genesis.config.cancun_time), #[cfg(feature = "optimism")] (Hardfork::Regolith, optimism_genesis_info.regolith_time), #[cfg(feature = "optimism")] @@ -2992,7 +2992,7 @@ Post-merge hard forks (timestamp based): // assert that the cancun time was picked up assert_eq!(genesis.config.cancun_time, Some(4661)); // assert that the prague time was picked up - assert_eq!(genesis.config.prague_time, Some(4662)); + assert_eq!(genesis.config.cancun_time, Some(4662)); } #[test] diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index e98bb9104de7..9a92b29bc7e0 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -15,46 +15,38 @@ use reth_primitives::{ }; use reth_provider::{BundleStateWithReceipts, ProviderError}; use revm::{db::CacheDB, Database}; -use revm_primitives::{AccountInfo, HashMap, U256}; +use revm_primitives::{keccak256, AccountInfo, Bytecode, HashMap, U256}; use url::Url; -fn convert_proof(proof: EIP1186AccountProofResponse) -> AccountProof { - let address = proof.address; - let balance = proof.balance; - let code_hash = proof.code_hash; - let nonce = proof.nonce.as_limbs()[0]; - let storage_hash = proof.storage_hash; - let account_proof = proof.account_proof; - let account_info = Account { nonce, balance, bytecode_hash: code_hash.into() }; - let storage_proofs = proof.storage_proof.into_iter().map(|storage_proof| { - let key = storage_proof.key; - let value = storage_proof.value; - let proof = storage_proof.proof; - let mut sp = StorageProof::new(key.0.into()); - sp.set_value(value); - sp.set_proof(proof); - sp - }); - AccountProof { - address, - info: Some(account_info), - proof: account_proof, - storage_root: storage_hash.into(), - storage_proofs: storage_proofs.collect(), - } -} - #[derive(Debug, Clone)] /// A struct that holds the input for a zkVM program to execute a block. pub struct SP1Input { /// The block that will be executed inside the zkVM program. pub block: RethBlock, /// Address to merkle proofs. - pub address_to_proof: HashMap, + pub address_to_proof: HashMap, /// Block number to block hash. pub block_hashes: HashMap, } +pub struct FullAccountProof { + account_proof: AccountProof, + code: Bytecode, +} + +impl FullAccountProof { + fn verify(&self, state_root: B256) -> eyre::Result<()> { + self.account_proof.verify(state_root)?; + // Assert that the code hash matches the code. + // TODO: there is an optimization for EMPTY_CODE_HASH If the self.code is empty. + let code_hash = keccak256(&self.code.0); + if self.account_proof.info.unwrap().bytecode_hash.unwrap() != code_hash { + return Err(eyre::eyre!("Code hash does not match the code")); + } + Ok(()) + } +} + async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { // We put imports here that are not used in the zkVM program. use alloy_provider::{Provider as AlloyProvider, ReqwestProvider}; diff --git a/testing/zkvm-script/src/provider_db.rs b/testing/zkvm-script/src/provider_db.rs index a41ba4d7c05b..72dd98be5278 100644 --- a/testing/zkvm-script/src/provider_db.rs +++ b/testing/zkvm-script/src/provider_db.rs @@ -4,7 +4,6 @@ use alloy_rpc_types::{BlockId, EIP1186AccountProofResponse}; use async_std::task; use futures::future::join_all; -// use alloy_transport::TransportResult; use crate::RethBlock; use alloy_transport_http::ReqwestTransport; use reth_primitives::{ @@ -24,6 +23,32 @@ use tokio::{runtime::Handle, task::block_in_place}; use crate::SP1Input; +fn convert_proof(proof: EIP1186AccountProofResponse) -> AccountProof { + let address = proof.address; + let balance = proof.balance; + let code_hash = proof.code_hash; + let nonce = proof.nonce.as_limbs()[0]; + let storage_hash = proof.storage_hash; + let account_proof = proof.account_proof; + let account_info = Account { nonce, balance, bytecode_hash: code_hash.into() }; + let storage_proofs = proof.storage_proof.into_iter().map(|storage_proof| { + let key = storage_proof.key; + let value = storage_proof.value; + let proof = storage_proof.proof; + let mut sp = StorageProof::new(key.0.into()); + sp.set_value(value); + sp.set_proof(proof); + sp + }); + AccountProof { + address, + info: Some(account_info), + proof: account_proof, + storage_root: storage_hash.into(), + storage_proofs: storage_proofs.collect(), + } +} + #[derive(Clone, Debug)] /// An implementation of a [`DatabaseRef`] that uses an [`ReqwestProvider`] to fetch data. pub struct RpcDb { @@ -147,8 +172,25 @@ impl RpcDb { pub async fn get_sp1_input(&self, block: &RethBlock) -> SP1Input { let proofs = self.get_proofs().await; + let converted_proofs: HashMap<_, _> = proofs + .iter() + .map(|(k, v)| { + let full_account_proof = FullAccountProof { + account_proof: convert_proof(v.clone()), + code: self + .address_to_account_info + .read() + .unwrap() + .get(k) + .unwrap() + .code + .unwrap(), + }; + (*k, full_account_proof) + }) + .collect(); let block_hashes = self.block_hashes.read().unwrap().clone(); - SP1Input { block: block.clone(), address_to_proof: proofs, block_hashes } + SP1Input { block: block.clone(), address_to_proof: converted_proofs, block_hashes } } } diff --git a/testing/zkvm-script/src/witness.rs b/testing/zkvm-script/src/witness.rs index 01d2284f63cc..baf460e91c08 100644 --- a/testing/zkvm-script/src/witness.rs +++ b/testing/zkvm-script/src/witness.rs @@ -9,7 +9,6 @@ use crate::{provider_db::RpcDb, SP1Input}; use revm::db::CacheDB; pub(crate) struct WitnessDb { - pub(crate) inner: InMemoryDB, pub address_to_account_info: HashMap, pub address_to_storage: HashMap>, pub block_hashes: HashMap, @@ -18,39 +17,29 @@ pub(crate) struct WitnessDb { impl WitnessDb { pub(crate) fn new(sp1_input: SP1Input) -> Self { - println!("WitnessDb::new"); - let mut inner = InMemoryDB::default(); - // let SP1Input { block, address_to_account_info, address_to_storage, block_hashes, .. } = - // sp1_input; - // for (proof, code) in merkle_proofs.into_iter().zip(code.into_iter()) { - // // TODO: verify proof against state_root - // // Note that we do not need to hash the code against the code_hash, since - // // `insert_contract` already does this. - // let address = proof.address; - // let code = if code.is_empty() { None } else { Some(Bytecode::new_raw(code.into())) }; - // let account_info = AccountInfo { - // nonce: proof.nonce.as_limbs()[0], // Is there a better way to do U64 -> u64? - // balance: proof.balance, - // code_hash: proof.code_hash, - // code, - // }; - // inner.insert_account_info(address, account_info); - // let storage_map = address_to_storage.get(&address); - // println!("inserting storage for address {}", address); - // if let Some(storage_map) = storage_map { - // for (index, value) in storage_map { - // println!("inserting storage {} {}", index, value); - // let _ = inner.insert_account_storage(address, *index, *value); - // } - // } - // // TODO: right now these are empty. - // // for storage_proof in proof.storage_proof { - // // // TODO: verify storage proof. - // // let slot = storage_proof.key.0; - // // let value = storage_proof.value; - // // let _ = inner.insert_account_storage(address, slot.into(), value); - // // } - // } + let state_root: B256 = sp1_input.block.state_root.into(); + let address_to_account_info = HashMap::new(); + let address_to_storage = HashMap::new(); + + for (address, proof) in sp1_input.address_to_proof { + proof.verify(state_root).expect("account proof verification failed"); + let account_proof = proof.account_proof; + let account_info = AccountInfo { + nonce: account_proof.nonce.as_limbs()[0], + balance: account_proof.balance, + code_hash: account_proof.code_hash, + code: proof.code, + }; + address_to_account_info.insert(address, account_info); + let storage_map = account_proof + .storage_proofs + .into_iter() + .map(|storage_proof| (storage_proof.key, storage_proof.value)) + .collect(); + address_to_storage.insert(address, storage_map); + } + let block_hashes = sp1_input.block_hashes; + Self { inner, address_to_account_info: HashMap::new(), @@ -64,10 +53,7 @@ impl WitnessDb { impl DatabaseRef for WitnessDb { type Error = ProviderError; - fn basic_ref( - &self, - address: revm_primitives::Address, - ) -> Result, Self::Error> { + fn basic_ref(&self, address: Address) -> Result, Self::Error> { Ok(self.address_to_account_info.get(&address).cloned()) } @@ -75,11 +61,7 @@ impl DatabaseRef for WitnessDb { unimplemented!() } - fn storage_ref( - &self, - address: revm_primitives::Address, - index: U256, - ) -> Result { + fn storage_ref(&self, address: Address, index: U256) -> Result { Ok(self.address_to_storage.get(&address).unwrap().get(&index).unwrap().clone()) } @@ -87,71 +69,3 @@ impl DatabaseRef for WitnessDb { Ok(self.block_hashes.get(&number).unwrap().clone()) } } - -// pub struct CheckDb { -// pub witness: CacheDB, -// pub rpc: CacheDB, -// } - -// impl Database for CheckDb { -// type Error = ProviderError; - -// fn basic( -// &mut self, -// address: revm_primitives::Address, -// ) -> Result, Self::Error> { -// let res1 = self.witness.basic(address).unwrap(); -// let res2 = self.rpc.basic(address).unwrap(); -// if res1 != res2 { -// println!("basic mismatch for address {}", address); -// println!("witness: {:?}", res1); -// println!("rpc: {:?}", res2); -// panic!("account mismatch"); -// } -// self.rpc.basic(address) -// } - -// fn code_by_hash(&mut self, code_hash: B256) -> Result -// { let res1 = self.witness.code_by_hash(code_hash).unwrap(); -// let res2 = self.rpc.code_by_hash(code_hash).unwrap(); -// if res1 != res2 { -// println!("code mismatch for hash {}", code_hash); -// println!("witness: {:?}", res1); -// println!("rpc: {:?}", res2); -// panic!("code mismatch"); -// } -// self.rpc.code_by_hash(code_hash) -// } - -// fn storage( -// &mut self, -// address: revm_primitives::Address, -// index: revm_primitives::U256, -// ) -> Result { -// let index_b = B256::from(index); -// let hash = keccak256(index_b); -// let hash_b: U256 = B256::from(hash).into(); -// let res1 = self.witness.storage(address, hash_b).unwrap(); -// let res2 = self.rpc.storage(address, index).unwrap(); -// if res1 != res2 { -// println!("storage mismatch for address {} index {}", address, index); -// println!("witness: {:?}", res1); -// println!("rpc: {:?}", res2); -// } else { -// println!("no storage mismatch for address {} index {}", address, index); -// } -// self.rpc.storage(address, index) -// } - -// fn block_hash(&mut self, number: revm_primitives::U256) -> Result { -// let res1 = self.witness.block_hash(number).unwrap(); -// let res2 = self.rpc.block_hash(number).unwrap(); -// if res1 != res2 { -// println!("block hash mismatch for number {}", number); -// println!("witness: {:?}", res1); -// println!("rpc: {:?}", res2); -// panic!("block_hash mismatch"); -// } -// self.rpc.block_hash(number) -// } -// } From 22cb9e0cf67b1cd02aed15552164edc2bfd81b14 Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Mon, 20 May 2024 00:27:35 -0700 Subject: [PATCH 27/30] Works --- testing/zkvm-script/src/cache.rs | 43 +++++++++++++++++--------- testing/zkvm-script/src/main.rs | 31 ++++++++++++++----- testing/zkvm-script/src/provider_db.rs | 43 ++++++++++++++++++++------ testing/zkvm-script/src/witness.rs | 2 +- 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/testing/zkvm-script/src/cache.rs b/testing/zkvm-script/src/cache.rs index 948c13a33860..ce0efc478c31 100644 --- a/testing/zkvm-script/src/cache.rs +++ b/testing/zkvm-script/src/cache.rs @@ -3,8 +3,9 @@ use alloy_rpc_types::{Block, BlockId, EIP1186AccountProofResponse}; use futures::Future; use reth_primitives::{ trie::{AccountProof, StorageProof}, - Account, Address, StorageKey, B256, U256, U64, + Account, Address, BlockNumberOrTag, StorageKey, B256, U256, U64, }; +use reth_provider::ProviderError; use revm_primitives::Bytes; use serde::{de::DeserializeOwned, Deserialize, Serialize}; use std::{ @@ -15,7 +16,7 @@ use std::{ sync::{Arc, RwLock}, }; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct CachedProvider { provider: ReqwestProvider, cache: Arc>>, @@ -76,10 +77,10 @@ impl CachedProvider { address: Address, storage_keys: Vec, block_id: BlockId, - ) -> EIP1186AccountProofResponse { + ) -> Result { let key = format!("get_proof_{:?}_{:?}_{:?}", address, storage_keys, block_id); if let Some(cached) = self.load_from_cache(&key) { - return cached; + return Ok(cached); } let proof = self .provider @@ -88,13 +89,17 @@ impl CachedProvider { .await .expect("Failed to get proof"); self.save_to_cache(&key, &proof); - proof + Ok(proof) } - pub async fn get_code_at(&self, address: Address, block_id: BlockId) -> Bytes { + pub async fn get_code_at( + &self, + address: Address, + block_id: BlockId, + ) -> Result { let key = format!("get_code_at_{:?}_{:?}", address, block_id); if let Some(cached) = self.load_from_cache(&key) { - return cached; + return Ok(cached); } let code = self .provider @@ -103,13 +108,19 @@ impl CachedProvider { .await .expect("Failed to get code"); self.save_to_cache(&key, &code); - code + Ok(code) } - pub async fn get_storage_at(&self, address: Address, index: U256, block_id: BlockId) -> U256 { + pub async fn get_storage_at( + &self, + address: Address, + index: U256, + block_id: BlockId, + ) -> Result { let key = format!("get_storage_at_{:?}_{:?}_{:?}", address, index, block_id); if let Some(cached) = self.load_from_cache(&key) { - return cached; + println!("Loaded from cache for get_storage_at"); + return Ok(cached); } let storage = self .provider @@ -118,13 +129,17 @@ impl CachedProvider { .await .expect("Failed to get storage"); self.save_to_cache(&key, &storage); - storage + Ok(storage) } - pub async fn get_block_by_number(&self, number: U64, full: bool) -> Option { + pub async fn get_block_by_number( + &self, + number: BlockNumberOrTag, + full: bool, + ) -> Result, ProviderError> { let key = format!("get_block_by_number_{:?}_{:?}", number, full); if let Some(cached) = self.load_from_cache(&key) { - return cached; + return Ok(cached); } let block = self .provider @@ -132,6 +147,6 @@ impl CachedProvider { .await .expect("Failed to get block"); self.save_to_cache(&key, &block); - block + Ok(block) } } diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index 1a81aa6854d5..af29e632eecd 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -4,7 +4,7 @@ pub mod provider_db; pub mod witness; use async_std::task; -use crate::{provider_db::RpcDb, witness::WitnessDb}; +use crate::{cache::CachedProvider, provider_db::RpcDb, witness::WitnessDb}; use eyre::Ok; use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; @@ -20,6 +20,8 @@ use url::Url; #[derive(Debug, Clone)] /// A struct that holds the input for a zkVM program to execute a block. pub struct SP1Input { + /// The previous block. + pub prev_block: RethBlock, /// The block that will be executed inside the zkVM program. pub block: RethBlock, /// Address to merkle proofs. @@ -76,14 +78,26 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { ) .shanghai_activated() .build(); - let provider_db = RpcDb::new(provider.clone(), (block_number - 1).into()); + // let cache_provider = CachedProvider::new(provider, "cache.json".into()); + + let prev_alloy_block = provider + .get_block_by_number((block_number - 1).into(), true) + .await? + .ok_or(eyre::eyre!("prev_block not found"))?; + let prev_block = RethBlock::try_from(prev_alloy_block)?; + let prev_state_root = prev_block.header.state_root; + + let cache_provider = provider.clone(); + let provider_db = + RpcDb::new(cache_provider.clone(), (block_number - 1).into(), prev_state_root.into()); // The reason we can clone the provider_db is all the stateful elements are within Arcs. let db = CacheDB::new(provider_db.clone()); - let address: Address = "0xdf02e18bb7fb735f5b1354400b16aeb19690627d".parse().unwrap(); + let address: Address = "0x4e68ccd3e89f51c3074ca5072bbac773960dfa36".parse().unwrap(); let account = task::block_on(provider_db.fetch_account_info(address)); // let account = provider_db.fetch_account_info(address).await; println!("Account: {:?}", account); + // cache_provider.save(); println!("Executing block with provider db..."); let executor = @@ -104,11 +118,12 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { block.header.number, ); println!("Done processing block!"); + // cache_provider.save(); - let _next_block = provider - .get_block_by_number((block_number + 1).into(), false) - .await? - .ok_or(eyre::eyre!("next_block not found"))?; + // let _next_block = provider + // .get_block_by_number((block_number + 1).into(), false) + // .await? + // .ok_or(eyre::eyre!("next_block not found"))?; // TODO: how do we compute the new state root here? Is there a way to do this incrementally? // // Unpacked `BundleState::state_root_slow` function @@ -116,7 +131,7 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { // block_state.hash_state_slow().state_root_with_updates(provider.tx_ref())?; // TODO: check that the computed state_root matches the next_block.header.state_root - let sp1_input = provider_db.get_sp1_input(&block).await; + let sp1_input = provider_db.get_sp1_input(&prev_block, &block).await; println!("Instantiating WitnessDb from SP1Input..."); // This code will be the code that runs inside the zkVM. diff --git a/testing/zkvm-script/src/provider_db.rs b/testing/zkvm-script/src/provider_db.rs index 98963646e940..5c813a083631 100644 --- a/testing/zkvm-script/src/provider_db.rs +++ b/testing/zkvm-script/src/provider_db.rs @@ -12,7 +12,7 @@ use reth_provider::ProviderError; use reth_revm::DatabaseRef; use revm_primitives::{AccountInfo, Bytecode, HashMap, HashSet}; -use crate::{FullAccountProof, RethBlock, SP1Input}; +use crate::{cache::CachedProvider, FullAccountProof, RethBlock, SP1Input}; fn convert_proof(proof: EIP1186AccountProofResponse) -> AccountProof { let address = proof.address; @@ -48,7 +48,8 @@ pub struct RpcDb { pub provider: ReqwestProvider, /// The [`BlockId`] that will be used when fetching data from the RPC. pub block: BlockId, - + /// The [`State`] + pub state_root: B256, /// A mapping from [`Address`] to [`AccountInfo`] for all addresses that have been fetched. pub address_to_account_info: Arc>>, pub address_to_storage: Arc>>>, @@ -56,10 +57,11 @@ pub struct RpcDb { } impl RpcDb { - pub fn new(provider: ReqwestProvider, block: BlockId) -> Self { + pub fn new(provider: ReqwestProvider, block: BlockId, state_root: B256) -> Self { RpcDb { provider, block, + state_root, address_to_account_info: Arc::new(RwLock::new(HashMap::new())), address_to_storage: Arc::new(RwLock::new(HashMap::new())), block_hashes: Arc::new(RwLock::new(HashMap::new())), @@ -94,6 +96,7 @@ impl RpcDb { code: Some(bytecode.clone()), }; println!("Inserting into address_to_account_info..."); + // Keep track of the account_info and code in the mappings for RpcDb. self.address_to_account_info.write().unwrap().insert(address, account_info.clone()); println!("Fetched"); @@ -155,8 +158,6 @@ impl RpcDb { .unwrap_or_else(Vec::new); let provider = self.provider.clone(); - let block = self.block; - async move { match provider.get_proof(*address, storage_keys).block_id(self.block).await { Ok(proof) => Some((*address, proof)), @@ -174,7 +175,7 @@ impl RpcDb { } /// Constructs an SP1Input from a block. - pub async fn get_sp1_input(&self, block: &RethBlock) -> SP1Input { + pub async fn get_sp1_input(&self, prev_block: &RethBlock, block: &RethBlock) -> SP1Input { println!("Constructing SP1Input for block {:?}...", block.header.number); let proofs = self.get_proofs().await; let address_to_account_info = self.address_to_account_info.read().unwrap(); @@ -188,7 +189,12 @@ impl RpcDb { }) .collect(); let block_hashes = self.block_hashes.read().unwrap().clone(); - SP1Input { block: block.clone(), address_to_proof: converted_proofs, block_hashes } + SP1Input { + prev_block: prev_block.clone(), + block: block.clone(), + address_to_proof: converted_proofs, + block_hashes, + } } } @@ -196,7 +202,14 @@ impl DatabaseRef for RpcDb { type Error = ProviderError; fn basic_ref(&self, address: Address) -> Result, Self::Error> { - Ok(Some(task::block_on(self.fetch_account_info(address)))) + if let Ok(handle) = tokio::runtime::Handle::try_current() { + Ok(Some(tokio::task::block_in_place(|| { + handle.block_on(self.fetch_account_info(address)) + }))) + } else { + panic!("No tokio runtime found"); + } + // Ok(Some(task::block_on(self.fetch_account_info(address)))) } fn code_by_hash_ref(&self, _code_hash: B256) -> Result { @@ -204,10 +217,20 @@ impl DatabaseRef for RpcDb { } fn storage_ref(&self, address: Address, index: U256) -> Result { - Ok(task::block_on(self.fetch_storage(address, index))) + if let Ok(handle) = tokio::runtime::Handle::try_current() { + Ok(tokio::task::block_in_place(|| handle.block_on(self.fetch_storage(address, index)))) + } else { + panic!("No tokio runtime found"); + } + // Ok(task::block_on(self.fetch_storage(address, index))) } fn block_hash_ref(&self, number: U256) -> Result { - Ok(task::block_on(self.fetch_block_hash(number))) + if let Ok(handle) = tokio::runtime::Handle::try_current() { + Ok(tokio::task::block_in_place(|| handle.block_on(self.fetch_block_hash(number)))) + } else { + panic!("No tokio runtime found"); + } + // Ok(task::block_on(self.fetch_block_hash(number))) } } diff --git a/testing/zkvm-script/src/witness.rs b/testing/zkvm-script/src/witness.rs index 35dc450b98a5..1e67ee1677d1 100644 --- a/testing/zkvm-script/src/witness.rs +++ b/testing/zkvm-script/src/witness.rs @@ -13,7 +13,7 @@ pub(crate) struct WitnessDb { impl WitnessDb { pub(crate) fn new(sp1_input: SP1Input) -> Self { - let state_root: B256 = sp1_input.block.state_root.into(); + let state_root: B256 = sp1_input.prev_block.state_root.into(); let mut address_to_account_info = HashMap::new(); let mut address_to_storage = HashMap::new(); From aafff2ded5bdceac92c940fa1671a57796142f6f Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Mon, 20 May 2024 00:46:41 -0700 Subject: [PATCH 28/30] more cleanup --- testing/zkvm-script/src/main.rs | 36 +++----------------------- testing/zkvm-script/src/provider_db.rs | 3 +-- 2 files changed, 4 insertions(+), 35 deletions(-) diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index af29e632eecd..44abe14c36b3 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -2,7 +2,6 @@ pub mod cache; pub mod provider_db; pub mod witness; -use async_std::task; use crate::{cache::CachedProvider, provider_db::RpcDb, witness::WitnessDb}; @@ -78,7 +77,6 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { ) .shanghai_activated() .build(); - // let cache_provider = CachedProvider::new(provider, "cache.json".into()); let prev_alloy_block = provider .get_block_by_number((block_number - 1).into(), true) @@ -93,12 +91,6 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { // The reason we can clone the provider_db is all the stateful elements are within Arcs. let db = CacheDB::new(provider_db.clone()); - let address: Address = "0x4e68ccd3e89f51c3074ca5072bbac773960dfa36".parse().unwrap(); - let account = task::block_on(provider_db.fetch_account_info(address)); - // let account = provider_db.fetch_account_info(address).await; - println!("Account: {:?}", account); - // cache_provider.save(); - println!("Executing block with provider db..."); let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()).executor(db); @@ -118,7 +110,6 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { block.header.number, ); println!("Done processing block!"); - // cache_provider.save(); // let _next_block = provider // .get_block_by_number((block_number + 1).into(), false) @@ -133,25 +124,6 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { let sp1_input = provider_db.get_sp1_input(&prev_block, &block).await; - println!("Instantiating WitnessDb from SP1Input..."); - // This code will be the code that runs inside the zkVM. - let witness_db_inner = WitnessDb::new(sp1_input.clone()); - let witness_db = CacheDB::new(witness_db_inner); - println!("Executing block with witness db..."); - let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) - .executor(witness_db); - let BlockExecutionOutput { state, receipts, .. } = executor.execute( - ( - &block - .clone() - .with_recovered_senders() - .ok_or(BlockValidationError::SenderRecoveryError)?, - (merkle_block_td + block.header.difficulty).into(), - ) - .into(), - )?; - println!("Done processing block!"); - Ok(sp1_input.clone()) } @@ -170,13 +142,10 @@ fn verify_stf(sp1_input: SP1Input) -> eyre::Result<()> { let block = sp1_input.block.clone(); let merkle_block_td = U256::from(0); // TODO: this should be an input? + println!("Instantiating WitnessDb from SP1Input..."); let witness_db_inner = WitnessDb::new(sp1_input.clone()); let witness_db = CacheDB::new(witness_db_inner); - - // let provider_db = RpcDb::new(provider.clone(), (block_number - 1).into()); - // let db = CacheDB::new(provider_db.clone()); - // let check_db = - // witness_db::CheckDb { witness: witness_db.clone(), rpc: RpcDb::new(provider_db) }; + println!("Executing block with witness db..."); // TODO: can we import `EthExecutorProvider` from reth-evm instead of reth-node-ethereum? let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) @@ -191,6 +160,7 @@ fn verify_stf(sp1_input: SP1Input) -> eyre::Result<()> { ) .into(), )?; + println!("Done processing block!"); let block_state = BundleStateWithReceipts::new( state, Receipts::from_block_receipt(receipts), diff --git a/testing/zkvm-script/src/provider_db.rs b/testing/zkvm-script/src/provider_db.rs index 5c813a083631..679d39417688 100644 --- a/testing/zkvm-script/src/provider_db.rs +++ b/testing/zkvm-script/src/provider_db.rs @@ -1,4 +1,3 @@ -use async_std::task; use futures::future::join_all; use std::sync::{Arc, RwLock}; @@ -12,7 +11,7 @@ use reth_provider::ProviderError; use reth_revm::DatabaseRef; use revm_primitives::{AccountInfo, Bytecode, HashMap, HashSet}; -use crate::{cache::CachedProvider, FullAccountProof, RethBlock, SP1Input}; +use crate::{FullAccountProof, RethBlock, SP1Input}; fn convert_proof(proof: EIP1186AccountProofResponse) -> AccountProof { let address = proof.address; From df7ed9e86ced0894b71067ac4c5acdd26b0c9d95 Mon Sep 17 00:00:00 2001 From: Roman Krasiuk Date: Mon, 20 May 2024 23:27:40 +0200 Subject: [PATCH 29/30] feat: compute root from proofs --- Cargo.lock | 2 + crates/trie/src/prefix_set/mod.rs | 2 +- testing/zkvm-script/Cargo.toml | 2 + testing/zkvm-script/src/main.rs | 170 +++++++++++++++++++++++++++++- 4 files changed, 173 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a8936ad065bf..0b3a88119506 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11269,7 +11269,9 @@ dependencies = [ name = "zkvm-script" version = "0.2.0-beta.7" dependencies = [ + "alloy-primitives", "alloy-provider", + "alloy-rlp", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-transport 0.0.0-reserved", "alloy-transport-http", diff --git a/crates/trie/src/prefix_set/mod.rs b/crates/trie/src/prefix_set/mod.rs index b556dd379075..acfc5411c1d6 100644 --- a/crates/trie/src/prefix_set/mod.rs +++ b/crates/trie/src/prefix_set/mod.rs @@ -133,7 +133,7 @@ impl PrefixSetMut { /// See also [PrefixSetMut::freeze]. #[derive(Debug, Default, Clone)] pub struct PrefixSet { - keys: Arc>, + pub keys: Arc>, index: usize, } diff --git a/testing/zkvm-script/Cargo.toml b/testing/zkvm-script/Cargo.toml index 6f203c60f5c2..ff2ade6c1d98 100644 --- a/testing/zkvm-script/Cargo.toml +++ b/testing/zkvm-script/Cargo.toml @@ -17,6 +17,8 @@ reth-consensus.workspace = true reth-interfaces = { path = "../../crates/interfaces", default-features = false } reth-evm.workspace = true revm.workspace = true +alloy-primitives.workspace = true +alloy-rlp.workspace = true alloy-rpc-types.workspace = true alloy-provider = { workspace = true, features = ["reqwest"] } alloy-transport-http.workspace = true diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index 44abe14c36b3..b2b535d1f485 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -5,13 +5,22 @@ pub mod witness; use crate::{cache::CachedProvider, provider_db::RpcDb, witness::WitnessDb}; +use alloy_primitives::Bytes; +use alloy_provider::Provider; +use alloy_rlp::{Decodable, Encodable}; use eyre::Ok; use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; use reth_interfaces::executor::BlockValidationError; use reth_primitives::{ - trie::AccountProof, Address, Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET, + revm::compat::into_reth_acc, + trie::{ + nodes::{TrieNode, CHILD_INDEX_RANGE}, + AccountProof, HashBuilder, Nibbles, TrieAccount, + }, + Address, Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET, }; use reth_provider::BundleStateWithReceipts; +use reth_trie::{HashedPostState, HashedStorage}; use revm::db::CacheDB; use revm_primitives::{keccak256, Bytecode, HashMap, U256}; use url::Url; @@ -104,7 +113,7 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { ) .into(), )?; - let _block_state = BundleStateWithReceipts::new( + let block_state = BundleStateWithReceipts::new( state, Receipts::from_block_receipt(receipts), block.header.number, @@ -120,6 +129,9 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { // // Unpacked `BundleState::state_root_slow` function // let (in_memory_state_root, in_memory_updates) = // block_state.hash_state_slow().state_root_with_updates(provider.tx_ref())?; + + let _state_root = update_state_root(&provider_db, &block_state).await?; + // TODO: check that the computed state_root matches the next_block.header.state_root let sp1_input = provider_db.get_sp1_input(&prev_block, &block).await; @@ -127,6 +139,160 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { Ok(sp1_input.clone()) } +async fn update_state_root( + provider_db: &RpcDb, + block_state: &BundleStateWithReceipts, +) -> eyre::Result { + let mut account_reverse_lookup = HashMap::::default(); + let mut storage_reverse_lookup = HashMap::::default(); + let mut hashed_state = HashedPostState::default(); + for (address, account) in block_state.bundle_accounts_iter() { + let hashed_address = keccak256(address); + account_reverse_lookup.insert(hashed_address, address); + hashed_state.accounts.insert(hashed_address, account.info.clone().map(into_reth_acc)); + + let mut hashed_storage = HashedStorage::new(account.status.was_destroyed()); + for (key, value) in &account.storage { + let slot = B256::new(key.to_be_bytes()); + let hashed_slot = keccak256(&slot); + storage_reverse_lookup.insert(hashed_slot, slot); + hashed_storage.storage.insert(hashed_slot, value.present_value); + } + hashed_state.storages.insert(hashed_address, hashed_storage); + } + + let mut rlp_buf = Vec::with_capacity(128); + let mut hash_builder = HashBuilder::default(); + let mut prefix_sets = hashed_state.construct_prefix_sets(); + let mut account_prefix_set_iter = + prefix_sets.account_prefix_set.keys.as_ref().iter().peekable(); + while let Some(account_nibbles) = account_prefix_set_iter.next() { + let hashed_address = B256::from_slice(&account_nibbles.pack()); + let storage_prefix_sets = + prefix_sets.storage_prefix_sets.remove(&hashed_address).unwrap_or_default(); + let storage_keys = storage_prefix_sets + .keys + .iter() + .map(|nibbles| *storage_reverse_lookup.get(&B256::from_slice(&nibbles.pack())).unwrap()) + .collect::>(); + + // TODO: calls should be parallelized + let proof = provider_db + .provider + .get_proof(*account_reverse_lookup.get(&hashed_address).unwrap(), storage_keys.clone()) + .await?; + + let storage_root = if proof.storage_proof.is_empty() { + proof.storage_hash + } else { + let mut storage_hash_builder = HashBuilder::default(); + let mut storage_prefix_set_iter = storage_prefix_sets.keys.as_ref().iter().peekable(); + while let Some(storage_nibbles) = storage_prefix_set_iter.next() { + let hashed_slot = B256::from_slice(&storage_nibbles.pack()); + let slot = storage_reverse_lookup.get(&hashed_slot).unwrap(); + let proof = proof.storage_proof.iter().find(|p| &p.key.0 == slot).unwrap(); + update_hash_builder_from_proof( + &mut storage_hash_builder, + &proof.proof, + Nibbles::default(), + storage_nibbles, + // TODO: handle zero + alloy_rlp::encode_fixed_size( + &hashed_state + .storages + .get(&hashed_address) + .and_then(|s| s.storage.get(&hashed_slot).cloned()) + .unwrap_or_default(), + ) + .as_ref(), + storage_prefix_set_iter.peek().copied(), + )?; + } + storage_hash_builder.root() + }; + + // TODO: handle destroyed accounts + rlp_buf.clear(); + TrieAccount::from(( + hashed_state.accounts.get(&hashed_address).unwrap().unwrap_or_default(), + storage_root, + )) + .encode(&mut rlp_buf); + + update_hash_builder_from_proof( + &mut hash_builder, + &proof.account_proof[..], + Nibbles::default(), + &account_nibbles, + &rlp_buf, + account_prefix_set_iter.peek().copied(), + )?; + } + + Ok(hash_builder.root()) +} + +fn update_hash_builder_from_proof( + hash_builder: &mut HashBuilder, + proof: &[Bytes], + current_key: Nibbles, + key: &Nibbles, + value: &[u8], + next: Option<&Nibbles>, +) -> eyre::Result<()> { + let Some(node) = proof.first() else { + // add leaf node + hash_builder.add_leaf(key.clone(), value); + return Ok(()) + }; + + match TrieNode::decode(&mut &node[..])? { + TrieNode::Branch(branch) => { + let mut stack_ptr = branch.as_ref().first_child_index(); + for index in CHILD_INDEX_RANGE { + let mut updated_key = current_key.clone(); + updated_key.push(index); + + // we should not be adding more + if Some(&updated_key) <= next { + return Ok(()) + } + + if branch.state_mask.is_bit_set(index) { + if key.starts_with(&updated_key) { + let rem = &proof[std::cmp::min(1, proof.len().saturating_sub(1))..]; + update_hash_builder_from_proof( + hash_builder, + rem, + updated_key, + key, + value, + next, + )?; + } else { + hash_builder.add_branch( + updated_key, + // proofs can only contain hashes + B256::from_slice(&branch.stack[stack_ptr]), + false, + ); + } + + stack_ptr += 1; + } + } + } + // overwrite the leaf node + TrieNode::Leaf(_) => { + hash_builder.add_leaf(key.clone(), value); + } + // noop + TrieNode::Extension(_) => {} + }; + + Ok(()) +} + /// Program that verifies the STF, run inside the zkVM. fn verify_stf(sp1_input: SP1Input) -> eyre::Result<()> { let chain_spec = ChainSpecBuilder::default() From fb19fc37b0bcf53016901fc3c090c5278d4c39e1 Mon Sep 17 00:00:00 2001 From: Uma Roy Date: Tue, 21 May 2024 14:00:38 -0700 Subject: [PATCH 30/30] Separating out the crates --- Cargo.lock | 1606 ++++++++++++++++- Dockerfile.zkvm | 3 + Makefile | 6 + crates/primitives/src/trie/proofs.rs | 4 +- testing/zkevm-lib/Cargo.lock | 740 ++++++++ testing/zkevm-lib/Cargo.toml | 26 + testing/zkevm-lib/README.md | 5 + testing/zkevm-lib/src/lib.rs | 93 + .../{zkvm-script => zkevm-lib}/src/witness.rs | 6 +- testing/zkvm-script/Cargo.toml | 4 +- testing/zkvm-script/src/main.rs | 143 +- testing/zkvm-script/src/provider_db.rs | 2 +- testing/zkvm/Cargo.toml | 7 +- testing/zkvm/src/main.rs | 7 +- 14 files changed, 2478 insertions(+), 174 deletions(-) create mode 100644 testing/zkevm-lib/Cargo.lock create mode 100644 testing/zkevm-lib/Cargo.toml create mode 100644 testing/zkevm-lib/README.md create mode 100644 testing/zkevm-lib/src/lib.rs rename testing/{zkvm-script => zkevm-lib}/src/witness.rs (95%) diff --git a/Cargo.lock b/Cargo.lock index 0b3a88119506..0881ff345726 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,17 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addchain" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2e69442aa5628ea6951fa33e24efe8313f4321a91bd729fc2f75bdfc858570" +dependencies = [ + "num-bigint 0.3.3", + "num-integer", + "num-traits", +] + [[package]] name = "addr2line" version = "0.21.0" @@ -23,7 +34,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -116,6 +127,24 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "alloy" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-contract", + "alloy-core", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-provider 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-rpc-client 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-signer 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-signer-wallet 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "reqwest 0.12.4", +] + [[package]] name = "alloy-chains" version = "0.1.18" @@ -124,7 +153,7 @@ checksum = "03fd095a9d70f4b1c5c102c84a4c782867a5c6416dbf6dcd42a63e7c7a89d3c8" dependencies = [ "alloy-rlp", "arbitrary", - "num_enum", + "num_enum 0.7.2", "proptest", "serde", "strum", @@ -143,6 +172,19 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-consensus" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "serde", + "sha2 0.10.8", +] + [[package]] name = "alloy-consensus" version = "0.1.0" @@ -156,6 +198,36 @@ dependencies = [ "serde", ] +[[package]] +name = "alloy-contract" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-network 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-primitives", + "alloy-provider 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-sol-types", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "futures", + "futures-util", + "thiserror", +] + +[[package]] +name = "alloy-core" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7253846c7bf55147775fd66c334abc1dd0a41e97e6155577b3dc513c6e66ef2" +dependencies = [ + "alloy-dyn-abi", + "alloy-json-abi", + "alloy-primitives", + "alloy-sol-types", +] + [[package]] name = "alloy-dyn-abi" version = "0.7.4" @@ -192,6 +264,19 @@ dependencies = [ "sha2 0.10.8", ] +[[package]] +name = "alloy-eips" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "c-kzg", + "once_cell", + "serde", +] + [[package]] name = "alloy-eips" version = "0.1.0" @@ -217,6 +302,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "alloy-genesis" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "serde", +] + [[package]] name = "alloy-genesis" version = "0.1.0" @@ -252,6 +347,17 @@ dependencies = [ "tracing", ] +[[package]] +name = "alloy-json-rpc" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "alloy-network" version = "0.1.0" @@ -259,16 +365,33 @@ source = "git+https://github.com/alloy-rs/alloy?rev=64feb9b#64feb9bc51c8021ea085 dependencies = [ "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", - "alloy-json-rpc", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-primitives", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", - "alloy-signer", + "alloy-signer 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-sol-types", "async-trait", "futures-utils-wasm", "thiserror", ] +[[package]] +name = "alloy-network" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-primitives", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-signer 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "async-trait", + "futures-utils-wasm", + "serde", + "thiserror", +] + [[package]] name = "alloy-node-bindings" version = "0.1.0" @@ -317,14 +440,14 @@ version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9b#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", - "alloy-json-rpc", - "alloy-network", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", + "alloy-network 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-primitives", - "alloy-rpc-client", + "alloy-rpc-client 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", - "alloy-rpc-types-trace", - "alloy-transport 0.1.0", - "alloy-transport-http", + "alloy-rpc-types-trace 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "async-stream", "async-trait", "auto_impl", @@ -340,6 +463,32 @@ dependencies = [ "url", ] +[[package]] +name = "alloy-provider" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-network 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-primitives", + "alloy-rpc-client 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-rpc-types-trace 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "async-stream", + "async-trait", + "auto_impl", + "dashmap", + "futures", + "lru", + "reqwest 0.12.4", + "serde_json", + "tokio", + "tracing", + "url", +] + [[package]] name = "alloy-rlp" version = "0.3.4" @@ -367,9 +516,29 @@ name = "alloy-rpc-client" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9b#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ - "alloy-json-rpc", - "alloy-transport 0.1.0", - "alloy-transport-http", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", + "futures", + "pin-project", + "reqwest 0.12.4", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tower", + "tracing", + "url", +] + +[[package]] +name = "alloy-rpc-client" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", "futures", "pin-project", "reqwest 0.12.4", @@ -404,6 +573,24 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-rpc-types" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-eips 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-genesis 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-primitives", + "alloy-rlp", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-sol-types", + "itertools 0.12.1", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "alloy-rpc-types" version = "0.1.0" @@ -475,6 +662,18 @@ dependencies = [ "serde_json", ] +[[package]] +name = "alloy-rpc-types-trace" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-serde 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "serde", + "serde_json", +] + [[package]] name = "alloy-serde" version = "0.1.0" @@ -485,6 +684,16 @@ dependencies = [ "serde_json", ] +[[package]] +name = "alloy-serde" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "serde", + "serde_json", +] + [[package]] name = "alloy-serde" version = "0.1.0" @@ -508,15 +717,28 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-signer" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-primitives", + "async-trait", + "auto_impl", + "elliptic-curve", + "k256", + "thiserror", +] + [[package]] name = "alloy-signer-wallet" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9b#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", - "alloy-network", + "alloy-network 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-primitives", - "alloy-signer", + "alloy-signer 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "async-trait", "coins-bip32", "coins-bip39", @@ -525,6 +747,21 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-signer-wallet" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-network 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-primitives", + "alloy-signer 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "async-trait", + "k256", + "rand 0.8.5", + "thiserror", +] + [[package]] name = "alloy-sol-macro" version = "0.7.4" @@ -608,7 +845,25 @@ name = "alloy-transport" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9b#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ - "alloy-json-rpc", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", + "base64 0.22.1", + "futures-util", + "futures-utils-wasm", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "url", + "wasm-bindgen-futures", +] + +[[package]] +name = "alloy-transport" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", "base64 0.22.1", "futures-util", "futures-utils-wasm", @@ -626,8 +881,8 @@ name = "alloy-transport-http" version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy?rev=64feb9b#64feb9bc51c8021ea08535694c44de84222f474e" dependencies = [ - "alloy-json-rpc", - "alloy-transport 0.1.0", + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "reqwest 0.12.4", "serde_json", "tower", @@ -635,6 +890,19 @@ dependencies = [ "url", ] +[[package]] +name = "alloy-transport-http" +version = "0.1.0" +source = "git+https://github.com/alloy-rs/alloy?rev=bfd0fda#bfd0fda492e560c3463d521958793c81bbeadfc1" +dependencies = [ + "alloy-json-rpc 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "alloy-transport 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=bfd0fda)", + "reqwest 0.12.4", + "serde_json", + "tower", + "url", +] + [[package]] name = "alloy-trie" version = "0.4.0" @@ -675,6 +943,15 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anstream" version = "0.6.14" @@ -764,7 +1041,7 @@ dependencies = [ "ark-serialize 0.3.0", "ark-std 0.3.0", "derivative", - "num-bigint", + "num-bigint 0.4.5", "num-traits", "paste", "rustc_version 0.3.3", @@ -784,7 +1061,7 @@ dependencies = [ "derivative", "digest 0.10.7", "itertools 0.10.5", - "num-bigint", + "num-bigint 0.4.5", "num-traits", "paste", "rustc_version 0.4.0", @@ -817,7 +1094,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" dependencies = [ - "num-bigint", + "num-bigint 0.4.5", "num-traits", "quote", "syn 1.0.109", @@ -829,7 +1106,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" dependencies = [ - "num-bigint", + "num-bigint 0.4.5", "num-traits", "proc-macro2", "quote", @@ -854,7 +1131,7 @@ checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" dependencies = [ "ark-std 0.4.0", "digest 0.10.7", - "num-bigint", + "num-bigint 0.4.5", ] [[package]] @@ -877,6 +1154,12 @@ dependencies = [ "rand 0.8.5", ] +[[package]] +name = "array-macro" +version = "2.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "220a2c618ab466efe41d0eace94dfeff1c35e3aa47891bdb95e1c0fefffd3c99" + [[package]] name = "arrayref" version = "0.3.7" @@ -1161,6 +1444,61 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +[[package]] +name = "axum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "backon" version = "0.4.4" @@ -1186,6 +1524,7 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", + "serde", ] [[package]] @@ -1344,13 +1683,52 @@ dependencies = [ "wyz", ] +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest 0.10.7", +] + +[[package]] +name = "blake2b_simd" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + +[[package]] +name = "blake3" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30cca6d3674597c30ddf2c587bf8d9d65c9a84d2326d941cc79c9842dfe0ef52" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", + "rayon", +] + +[[package]] +name = "blake3-zkvm" +version = "0.1.0" +source = "git+https://github.com/sp1-patches/BLAKE3.git?branch=patch-blake3_zkvm/v.1.0.0#bac2d59f9122b07a4d91475560b4c3214ae62444" + [[package]] name = "block-buffer" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -1359,7 +1737,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -1368,7 +1746,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -1385,6 +1763,19 @@ dependencies = [ "piper", ] +[[package]] +name = "bls12_381" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3c196a77437e7cc2fb515ce413a6401291578b5afc8ecb29a3c7ab957f05941" +dependencies = [ + "ff 0.12.1", + "group 0.12.1", + "pairing", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "blst" version = "0.3.11" @@ -1407,7 +1798,7 @@ dependencies = [ "boa_interner", "boa_macros", "indexmap 2.2.6", - "num-bigint", + "num-bigint 0.4.5", "rustc-hash", ] @@ -1434,10 +1825,10 @@ dependencies = [ "indexmap 2.2.6", "intrusive-collections", "itertools 0.12.1", - "num-bigint", + "num-bigint 0.4.5", "num-integer", "num-traits", - "num_enum", + "num_enum 0.7.2", "once_cell", "paste", "pollster", @@ -1509,7 +1900,7 @@ dependencies = [ "boa_profiler", "fast-float", "icu_properties", - "num-bigint", + "num-bigint 0.4.5", "num-traits", "regress", "rustc-hash", @@ -1760,7 +2151,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -1866,7 +2257,7 @@ dependencies = [ "bech32", "bs58", "digest 0.10.7", - "generic-array", + "generic-array 0.14.7", "hex", "ripemd", "serde", @@ -1946,6 +2337,7 @@ dependencies = [ "encode_unicode", "lazy_static", "libc", + "unicode-width", "windows-sys 0.52.0", ] @@ -1974,6 +2366,12 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3618cccc083bb987a415d85c02ca6c9994ea5b44731ec28b9ecf09658655fba9" +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + [[package]] name = "convert_case" version = "0.4.0" @@ -2094,6 +2492,19 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + [[package]] name = "crossbeam-channel" version = "0.5.13" @@ -2122,6 +2533,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -2165,7 +2585,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.7", "rand_core 0.6.4", "subtle", "zeroize", @@ -2177,7 +2597,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.7", "typenum", ] @@ -2187,7 +2607,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" dependencies = [ - "generic-array", + "generic-array 0.14.7", "subtle", ] @@ -2576,7 +2996,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -2696,12 +3116,24 @@ dependencies = [ "winapi", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "downcast" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + [[package]] name = "dunce" version = "1.0.4" @@ -2797,6 +3229,12 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + [[package]] name = "elliptic-curve" version = "0.13.8" @@ -2806,9 +3244,9 @@ dependencies = [ "base16ct", "crypto-bigint", "digest 0.10.7", - "ff", - "generic-array", - "group", + "ff 0.13.0", + "generic-array 0.14.7", + "group 0.13.0", "pkcs8", "rand_core 0.6.4", "sec1", @@ -2906,7 +3344,7 @@ version = "3.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee" dependencies = [ - "num-bigint", + "num-bigint 0.4.5", "num-traits", "proc-macro2", "quote", @@ -3011,9 +3449,9 @@ dependencies = [ "const-hex", "elliptic-curve", "ethabi", - "generic-array", + "generic-array 0.14.7", "k256", - "num_enum", + "num_enum 0.7.2", "open-fastrlp", "rand 0.8.5", "rlp", @@ -3253,6 +3691,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ff" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" +dependencies = [ + "bitvec", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "ff" version = "0.13.0" @@ -3260,10 +3709,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ "bitvec", + "byteorder", + "ff_derive", "rand_core 0.6.4", "subtle", ] +[[package]] +name = "ff_derive" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9f54704be45ed286151c5e11531316eaef5b8f5af7d597b806fdb8af108d84a" +dependencies = [ + "addchain", + "cfg-if", + "num-bigint 0.3.3", + "num-integer", + "num-traits", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "fiat-crypto" version = "0.2.9" @@ -3522,6 +3989,12 @@ dependencies = [ "byteorder", ] +[[package]] +name = "gcd" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d758ba1b47b00caf47f24925c0074ecb20d6dfcffe7f6d53395c0465674841a" + [[package]] name = "generic-array" version = "0.14.7" @@ -3533,6 +4006,16 @@ dependencies = [ "zeroize", ] +[[package]] +name = "generic-array" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe739944a5406424e080edccb6add95685130b9f160d5407c639c7df0c5836b0" +dependencies = [ + "serde", + "typenum", +] + [[package]] name = "getrandom" version = "0.1.16" @@ -3573,6 +4056,19 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +[[package]] +name = "git2" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" +dependencies = [ + "bitflags 2.5.0", + "libc", + "libgit2-sys", + "log", + "url", +] + [[package]] name = "glob" version = "0.3.1" @@ -3625,13 +4121,25 @@ dependencies = [ "web-sys", ] +[[package]] +name = "group" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" +dependencies = [ + "ff 0.12.1", + "memuse", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "group" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "ff", + "ff 0.13.0", "rand_core 0.6.4", "subtle", ] @@ -3655,6 +4163,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "half" version = "2.4.1" @@ -3665,6 +4192,29 @@ dependencies = [ "crunchy", ] +[[package]] +name = "halo2" +version = "0.1.0-beta.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a23c779b38253fe1538102da44ad5bd5378495a61d2c4ee18d64eaa61ae5995" +dependencies = [ + "halo2_proofs", +] + +[[package]] +name = "halo2_proofs" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e925780549adee8364c7f2b685c753f6f3df23bde520c67416e93bf615933760" +dependencies = [ + "blake2b_simd", + "ff 0.12.1", + "group 0.12.1", + "pasta_curves 0.4.1", + "rand_core 0.6.4", + "rayon", +] + [[package]] name = "hash-db" version = "0.15.2" @@ -3802,7 +4352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" dependencies = [ "digest 0.9.0", - "generic-array", + "generic-array 0.14.7", "hmac 0.8.1", ] @@ -3952,7 +4502,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -3975,9 +4525,11 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "httparse", + "httpdate", "itoa", "pin-project-lite", "smallvec", @@ -4385,6 +4937,19 @@ dependencies = [ "serde", ] +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + [[package]] name = "indoc" version = "2.0.5" @@ -4422,7 +4987,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ "block-padding", - "generic-array", + "generic-array 0.14.7", ] [[package]] @@ -4663,7 +5228,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d0bb047e79a143b32ea03974a6bf59b62c2a4c5f5d42a381c907a8bbb3f75c0" dependencies = [ "heck 0.4.1", - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 2.0.65", @@ -4759,6 +5324,20 @@ dependencies = [ "simple_asn1", ] +[[package]] +name = "jubjub" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a575df5f985fe1cd5b2b05664ff6accfc46559032b954529fd225a2168d27b0f" +dependencies = [ + "bitvec", + "bls12_381", + "ff 0.12.1", + "group 0.12.1", + "rand_core 0.6.4", + "subtle", +] + [[package]] name = "k256" version = "0.13.3" @@ -4841,6 +5420,18 @@ dependencies = [ "cc", ] +[[package]] +name = "libgit2-sys" +version = "0.16.2+1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4126d8b4ee5c9d9ea891dd875cfdc1e9d0950437179104b183d7d8a74d24e8" +dependencies = [ + "cc", + "libc", + "libz-sys", + "pkg-config", +] + [[package]] name = "libloading" version = "0.8.3" @@ -5054,6 +5645,18 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "libz-sys" +version = "1.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -5177,6 +5780,12 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "memchr" version = "2.7.2" @@ -5210,6 +5819,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "memuse" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2145869435ace5ea6ea3d35f59be559317ec9a0d04e1812d5f185a87b6d36f1a" + [[package]] name = "metrics" version = "0.21.1" @@ -5536,6 +6151,12 @@ dependencies = [ "reth-node-ethereum", ] +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "7.1.3" @@ -5562,7 +6183,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ - "num-bigint", + "num-bigint 0.4.5", "num-complex", "num-integer", "num-iter", @@ -5570,6 +6191,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6f7833f2cbf2360a6cfd58cd41a53aa7a90bd4c202f5b1c7dd2ed73c57b2c3" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-bigint" version = "0.4.5" @@ -5632,7 +6264,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "num-bigint", + "num-bigint 0.4.5", "num-integer", "num-traits", ] @@ -5657,13 +6289,34 @@ dependencies = [ "libc", ] +[[package]] +name = "num_enum" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +dependencies = [ + "num_enum_derive 0.5.11", +] + [[package]] name = "num_enum" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ - "num_enum_derive", + "num_enum_derive 0.7.2", +] + +[[package]] +name = "num_enum_derive" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 1.0.109", ] [[package]] @@ -5672,7 +6325,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 2.0.65", @@ -5687,6 +6340,12 @@ dependencies = [ "libc", ] +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + [[package]] name = "nybbles" version = "0.2.1" @@ -5818,6 +6477,252 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "p3-air" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "p3-field", + "p3-matrix", +] + +[[package]] +name = "p3-baby-bear" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "num-bigint 0.4.5", + "p3-field", + "p3-mds", + "p3-poseidon2", + "p3-symmetric", + "rand 0.8.5", + "serde", +] + +[[package]] +name = "p3-blake3" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "blake3", + "p3-symmetric", +] + +[[package]] +name = "p3-bn254-fr" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "ff 0.13.0", + "num-bigint 0.4.5", + "p3-field", + "p3-poseidon2", + "p3-symmetric", + "rand 0.8.5", + "serde", +] + +[[package]] +name = "p3-challenger" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "p3-field", + "p3-maybe-rayon", + "p3-symmetric", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-commit" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "itertools 0.12.1", + "p3-challenger", + "p3-field", + "p3-matrix", + "p3-util", + "serde", +] + +[[package]] +name = "p3-dft" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-field" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "itertools 0.12.1", + "num-bigint 0.4.5", + "num-traits", + "p3-util", + "rand 0.8.5", + "serde", +] + +[[package]] +name = "p3-fri" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "itertools 0.12.1", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-interpolation", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-interpolation" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "p3-field", + "p3-matrix", + "p3-util", +] + +[[package]] +name = "p3-keccak" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "p3-symmetric", + "tiny-keccak", +] + +[[package]] +name = "p3-keccak-air" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "p3-air", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "tracing", +] + +[[package]] +name = "p3-matrix" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "itertools 0.12.1", + "p3-field", + "p3-maybe-rayon", + "p3-util", + "rand 0.8.5", + "serde", + "tracing", +] + +[[package]] +name = "p3-maybe-rayon" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "rayon", +] + +[[package]] +name = "p3-mds" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "itertools 0.12.1", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-symmetric", + "p3-util", + "rand 0.8.5", +] + +[[package]] +name = "p3-merkle-tree" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "itertools 0.12.1", + "p3-commit", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-symmetric", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-poseidon2" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "gcd", + "p3-field", + "p3-mds", + "p3-symmetric", + "rand 0.8.5", +] + +[[package]] +name = "p3-symmetric" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "itertools 0.12.1", + "p3-field", + "serde", +] + +[[package]] +name = "p3-uni-stark" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "itertools 0.12.1", + "p3-air", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-matrix", + "p3-maybe-rayon", + "p3-util", + "serde", + "tracing", +] + +[[package]] +name = "p3-util" +version = "0.1.0" +source = "git+https://github.com/Plonky3/Plonky3.git?branch=sp1#da0489b75025ec17f1100952694d8b7879c2b43e" +dependencies = [ + "serde", +] + [[package]] name = "page_size" version = "0.6.0" @@ -5828,6 +6733,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "pairing" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135590d8bdba2b31346f9cd1fb2a912329f5135e832a4f422942eb6ead8b6b3b" +dependencies = [ + "group 0.12.1", +] + [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -5849,7 +6763,7 @@ version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -5909,6 +6823,36 @@ dependencies = [ "windows-targets 0.52.5", ] +[[package]] +name = "pasta_curves" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc65faf8e7313b4b1fbaa9f7ca917a0eed499a9663be71477f87993604341d8" +dependencies = [ + "blake2b_simd", + "ff 0.12.1", + "group 0.12.1", + "lazy_static", + "rand 0.8.5", + "static_assertions", + "subtle", +] + +[[package]] +name = "pasta_curves" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" +dependencies = [ + "blake2b_simd", + "ff 0.13.0", + "group 0.13.0", + "lazy_static", + "rand 0.8.5", + "static_assertions", + "subtle", +] + [[package]] name = "paste" version = "1.0.15" @@ -6282,6 +7226,16 @@ dependencies = [ "uint", ] +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + [[package]] name = "proc-macro-crate" version = "3.1.0" @@ -6381,6 +7335,38 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "prost" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb1435c188b76130da55f17a466d252ff7b1418b2ad3e037d127b94e3411f29" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" +dependencies = [ + "anyhow", + "itertools 0.10.5", + "proc-macro2", + "quote", + "syn 2.0.65", +] + +[[package]] +name = "prost-types" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9091c90b0a32608e984ff2fa4091273cbdd755d54935c51d520887f4a1dbd5b0" +dependencies = [ + "prost", +] + [[package]] name = "public-ip" version = "0.2.2" @@ -6596,6 +7582,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rayon-scan" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f87cc11a0140b4b0da0ffc889885760c61b13672d80a908920b2c0df078fa14" +dependencies = [ + "rayon", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -6690,7 +7685,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", @@ -6707,7 +7702,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-rustls 0.24.1", @@ -6730,8 +7725,11 @@ checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ "base64 0.22.1", "bytes", + "encoding_rs", + "futures-channel", "futures-core", "futures-util", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "http-body-util", @@ -6754,19 +7752,37 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", + "system-configuration", "tokio", "tokio-native-tls", "tokio-rustls 0.25.0", + "tokio-util", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams", "web-sys", "webpki-roots 0.26.1", "winreg 0.52.0", ] +[[package]] +name = "reqwest-middleware" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a45d100244a467870f6cb763c4484d010a6bed6bd610b3676e3825d93fb4cfbd" +dependencies = [ + "anyhow", + "async-trait", + "http 1.1.0", + "reqwest 0.12.4", + "serde", + "thiserror", + "tower-service", +] + [[package]] name = "resolv-conf" version = "0.7.0" @@ -7086,7 +8102,7 @@ dependencies = [ "assert_matches", "discv5", "enr 0.12.0", - "generic-array", + "generic-array 0.14.7", "parking_lot 0.12.2", "rand 0.8.5", "reth-net-common", @@ -7187,10 +8203,10 @@ name = "reth-e2e-test-utils" version = "0.2.0-beta.7" dependencies = [ "alloy-consensus 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", - "alloy-network", + "alloy-network 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", - "alloy-signer", - "alloy-signer-wallet", + "alloy-signer 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", + "alloy-signer-wallet 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "eyre", "futures-util", "jsonrpsee", @@ -7227,7 +8243,7 @@ dependencies = [ "digest 0.10.7", "educe", "futures", - "generic-array", + "generic-array 0.14.7", "hmac 0.12.1", "pin-project", "rand 0.8.5", @@ -7571,7 +8587,7 @@ name = "reth-network" version = "0.2.0-beta.7" dependencies = [ "alloy-node-bindings", - "alloy-provider", + "alloy-provider 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-rlp", "aquamarine", "auto_impl", @@ -8243,7 +9259,7 @@ dependencies = [ "alloy-rpc-types-anvil", "alloy-rpc-types-beacon", "alloy-rpc-types-engine", - "alloy-rpc-types-trace", + "alloy-rpc-types-trace 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "arbitrary", "bytes", "jsonrpsee-types", @@ -8506,7 +9522,7 @@ source = "git+https://github.com/paradigmxyz/evm-inspectors?rev=5a4fd5e#5a4fd5e3 dependencies = [ "alloy-primitives", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", - "alloy-rpc-types-trace", + "alloy-rpc-types-trace 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-sol-types", "anstyle", "boa_engine", @@ -8692,6 +9708,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "rrs-lib" +version = "0.1.0" +source = "git+https://github.com/GregAC/rrs.git#b23afc16b4e6a1fb5c4a73eb1e337e9400816507" +dependencies = [ + "downcast-rs", + "num_enum 0.5.11", + "paste", +] + [[package]] name = "ruint" version = "1.12.1" @@ -8704,7 +9730,7 @@ dependencies = [ "ark-ff 0.4.2", "bytes", "fastrlp", - "num-bigint", + "num-bigint 0.4.5", "num-traits", "parity-scale-codec", "primitive-types", @@ -8965,7 +9991,7 @@ version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2", "quote", "syn 1.0.109", @@ -9030,7 +10056,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der", - "generic-array", + "generic-array 0.14.7", "pkcs8", "subtle", "zeroize", @@ -9178,6 +10204,16 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + [[package]] name = "serde_qs" version = "0.8.5" @@ -9423,7 +10459,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" dependencies = [ - "num-bigint", + "num-bigint 0.4.5", "num-traits", "thiserror", "time", @@ -9435,6 +10471,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "size" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fed904c7fb2856d868b92464fc8fa597fce366edea1a9cbfaa8cb5fe080bd6d" + [[package]] name = "sketches-ddsketch" version = "0.2.2" @@ -9512,6 +10554,76 @@ dependencies = [ "sha-1", ] +[[package]] +name = "sp1-core" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "anyhow", + "arrayref", + "bincode", + "blake3", + "blake3-zkvm", + "cfg-if", + "curve25519-dalek", + "elf", + "elliptic-curve", + "generic-array 1.0.0", + "hex", + "itertools 0.12.1", + "k256", + "log", + "nohash-hasher", + "num", + "num-bigint 0.4.5", + "num_cpus", + "p3-air", + "p3-baby-bear", + "p3-blake3", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-fri", + "p3-keccak", + "p3-keccak-air", + "p3-matrix", + "p3-maybe-rayon", + "p3-merkle-tree", + "p3-poseidon2", + "p3-symmetric", + "p3-uni-stark", + "p3-util", + "rayon-scan", + "rrs-lib", + "serde", + "serde_with", + "serial_test", + "size", + "snowbridge-amcl", + "sp1-derive", + "sp1-primitives", + "strum", + "strum_macros", + "tempfile", + "thiserror", + "tracing", + "tracing-forest", + "tracing-subscriber", + "typenum", + "web-time", +] + +[[package]] +name = "sp1-derive" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "sp1-precompiles" version = "0.1.0" @@ -9529,6 +10641,239 @@ dependencies = [ "snowbridge-amcl", ] +[[package]] +name = "sp1-primitives" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "itertools 0.12.1", + "lazy_static", + "p3-baby-bear", + "p3-field", + "p3-poseidon2", + "p3-symmetric", +] + +[[package]] +name = "sp1-prover" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "anyhow", + "backtrace", + "bincode", + "clap", + "dirs", + "futures", + "hex", + "indicatif", + "itertools 0.12.1", + "num-bigint 0.4.5", + "p3-baby-bear", + "p3-bn254-fr", + "p3-challenger", + "p3-commit", + "p3-field", + "rayon", + "reqwest 0.12.4", + "serde", + "serde_json", + "serial_test", + "sha2 0.10.8", + "size", + "sp1-core", + "sp1-primitives", + "sp1-recursion-circuit", + "sp1-recursion-compiler", + "sp1-recursion-core", + "sp1-recursion-gnark-ffi", + "sp1-recursion-program", + "subtle-encoding", + "tempfile", + "thiserror", + "tokio", + "tracing", + "tracing-appender", + "tracing-subscriber", +] + +[[package]] +name = "sp1-recursion-circuit" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "bincode", + "itertools 0.12.1", + "p3-air", + "p3-baby-bear", + "p3-bn254-fr", + "p3-commit", + "p3-field", + "p3-fri", + "p3-matrix", + "p3-util", + "serde", + "sp1-core", + "sp1-recursion-compiler", + "sp1-recursion-core", + "sp1-recursion-derive", + "sp1-recursion-program", +] + +[[package]] +name = "sp1-recursion-compiler" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "backtrace", + "itertools 0.12.1", + "p3-air", + "p3-baby-bear", + "p3-bn254-fr", + "p3-commit", + "p3-field", + "p3-fri", + "p3-matrix", + "p3-poseidon2", + "p3-symmetric", + "p3-util", + "serde", + "serde_json", + "serial_test", + "sp1-core", + "sp1-recursion-core", + "sp1-recursion-derive", + "tracing", +] + +[[package]] +name = "sp1-recursion-core" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "arrayref", + "backtrace", + "ff 0.13.0", + "hashbrown 0.14.5", + "itertools 0.12.1", + "p3-air", + "p3-baby-bear", + "p3-bn254-fr", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-fri", + "p3-matrix", + "p3-maybe-rayon", + "p3-merkle-tree", + "p3-poseidon2", + "p3-symmetric", + "serde", + "serde_with", + "sp1-core", + "sp1-derive", + "sp1-primitives", + "static_assertions", + "tracing", + "zkhash", +] + +[[package]] +name = "sp1-recursion-derive" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sp1-recursion-gnark-ffi" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "bindgen", + "cc", + "crossbeam", + "log", + "num-bigint 0.4.5", + "p3-baby-bear", + "p3-field", + "rand 0.8.5", + "reqwest 0.12.4", + "serde", + "serde_json", + "sp1-recursion-compiler", + "subtle-encoding", + "tempfile", +] + +[[package]] +name = "sp1-recursion-program" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "array-macro", + "itertools 0.12.1", + "p3-air", + "p3-baby-bear", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-fri", + "p3-matrix", + "p3-maybe-rayon", + "p3-merkle-tree", + "p3-poseidon2", + "p3-symmetric", + "p3-util", + "rand 0.8.5", + "serde", + "sp1-core", + "sp1-recursion-compiler", + "sp1-recursion-core", + "tracing", +] + +[[package]] +name = "sp1-sdk" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1#6ee15b1169823907cf422d88f8dfbf284d0a18be" +dependencies = [ + "alloy", + "anyhow", + "async-trait", + "axum", + "bincode", + "dirs", + "dotenv", + "futures", + "hex", + "indicatif", + "log", + "num-bigint 0.4.5", + "p3-commit", + "p3-field", + "p3-matrix", + "prost", + "prost-types", + "reqwest 0.12.4", + "reqwest-middleware", + "serde", + "serde_json", + "sha2 0.10.8", + "sp1-core", + "sp1-prover", + "tempfile", + "tokio", + "tracing", + "twirp", + "vergen", +] + [[package]] name = "sp1-zkvm" version = "0.1.0" @@ -9664,6 +11009,15 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +[[package]] +name = "subtle-encoding" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dcb1ed7b8330c5eed5441052651dd7a12c75e2ed88f2ec024ae1fa3a5e59945" +dependencies = [ + "zeroize", +] + [[package]] name = "sucds" version = "0.8.1" @@ -9737,6 +11091,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "synstructure" version = "0.13.1" @@ -10137,6 +11497,17 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.40", +] + [[package]] name = "toml_edit" version = "0.21.1" @@ -10269,6 +11640,19 @@ dependencies = [ "valuable", ] +[[package]] +name = "tracing-forest" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee40835db14ddd1e3ba414292272eddde9dad04d3d4b65509656414d1c42592f" +dependencies = [ + "ansi_term", + "smallvec", + "thiserror", + "tracing", + "tracing-subscriber", +] + [[package]] name = "tracing-futures" version = "0.2.5" @@ -10487,6 +11871,28 @@ dependencies = [ "utf-8", ] +[[package]] +name = "twirp" +version = "0.3.0" +source = "git+https://github.com/github/twirp-rs.git?rev=c85f31f9c54957374e7dcb3534fc52cff0aa2dc5#c85f31f9c54957374e7dcb3534fc52cff0aa2dc5" +dependencies = [ + "async-trait", + "axum", + "bytes", + "futures", + "http 1.1.0", + "http-body-util", + "hyper 1.3.1", + "prost", + "reqwest 0.12.4", + "serde", + "serde_json", + "thiserror", + "tokio", + "tower", + "url", +] + [[package]] name = "txpool-tracing" version = "0.0.0" @@ -10582,7 +11988,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402" dependencies = [ - "generic-array", + "generic-array 0.14.7", "subtle", ] @@ -10682,6 +12088,7 @@ dependencies = [ "anyhow", "cargo_metadata", "cfg-if", + "git2", "regex", "rustversion", "time", @@ -10834,6 +12241,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -11265,16 +12682,60 @@ dependencies = [ "syn 2.0.65", ] +[[package]] +name = "zkevm-lib" +version = "0.2.0-beta.7" +dependencies = [ + "eyre", + "reth-consensus", + "reth-evm", + "reth-interfaces", + "reth-node-ethereum", + "reth-primitives", + "reth-revm", + "reth-trie", + "revm", + "revm-primitives", + "serde", + "serde_json", +] + +[[package]] +name = "zkhash" +version = "0.2.0" +source = "git+https://github.com/HorizenLabs/poseidon2#bb476b9ca38198cf5092487283c8b8c5d4317c4e" +dependencies = [ + "ark-ff 0.4.2", + "ark-std 0.4.0", + "bitvec", + "blake2", + "bls12_381", + "byteorder", + "cfg-if", + "group 0.12.1", + "group 0.13.0", + "halo2", + "hex", + "jubjub", + "lazy_static", + "pasta_curves 0.5.1", + "rand 0.8.5", + "serde", + "sha2 0.10.8", + "sha3", + "subtle", +] + [[package]] name = "zkvm-script" version = "0.2.0-beta.7" dependencies = [ "alloy-primitives", - "alloy-provider", + "alloy-provider 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-rlp", "alloy-rpc-types 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "alloy-transport 0.0.0-reserved", - "alloy-transport-http", + "alloy-transport-http 0.1.0 (git+https://github.com/alloy-rs/alloy?rev=64feb9b)", "async-std", "ethers-providers", "eyre", @@ -11291,17 +12752,16 @@ dependencies = [ "revm-primitives", "serde", "serde_json", + "sp1-sdk", "tokio", "url", + "zkevm-lib", ] [[package]] name = "zkvm-test" version = "0.2.0-beta.7" dependencies = [ - "reth-consensus", - "reth-evm", - "reth-interfaces", "reth-primitives", "sp1-zkvm", ] diff --git a/Dockerfile.zkvm b/Dockerfile.zkvm index 926fc1c167f5..f7912c9dc2dc 100644 --- a/Dockerfile.zkvm +++ b/Dockerfile.zkvm @@ -22,4 +22,7 @@ ENV CARGO_BUILD_TARGET="riscv32im-succinct-zkvm-elf" ENV CC="gcc" ENV CC_riscv32im_succinct_zkvm_elf="/opt/riscv/bin/riscv32-unknown-elf-gcc -mstrict-align" +# Set the entrypoint to use bash so you can override the command later +# ENTRYPOINT ["/bin/bash"] + RUN cargo build -p zkvm-test --release --ignore-rust-version \ No newline at end of file diff --git a/Makefile b/Makefile index a6a385a13314..e649b56a7cc8 100644 --- a/Makefile +++ b/Makefile @@ -474,3 +474,9 @@ pr: make lint && \ make docs && \ make test + +sp1: + docker build -t sp1-zkvm-test -f Dockerfile.zkvm . + +sp1-run: + docker run --rm -it sp1-zkvm-test cargo build -p zkvm-test --release --ignore-rust-version \ No newline at end of file diff --git a/crates/primitives/src/trie/proofs.rs b/crates/primitives/src/trie/proofs.rs index d3a2db66e19b..d720cb2c4584 100644 --- a/crates/primitives/src/trie/proofs.rs +++ b/crates/primitives/src/trie/proofs.rs @@ -9,7 +9,7 @@ use alloy_rlp::encode_fixed_size; use alloy_trie::EMPTY_ROOT_HASH; /// The merkle proof with the relevant account info. -#[derive(PartialEq, Eq, Debug, Clone)] +#[derive(PartialEq, Eq, Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct AccountProof { /// The address associated with the account. pub address: Address, @@ -75,7 +75,7 @@ impl AccountProof { } /// The merkle proof of the storage entry. -#[derive(PartialEq, Eq, Default, Debug, Clone)] +#[derive(PartialEq, Eq, Default, Debug, Clone, serde::Serialize, serde::Deserialize)] pub struct StorageProof { /// The raw storage key. pub key: B256, diff --git a/testing/zkevm-lib/Cargo.lock b/testing/zkevm-lib/Cargo.lock new file mode 100644 index 000000000000..d50e50e888bc --- /dev/null +++ b/testing/zkevm-lib/Cargo.lock @@ -0,0 +1,740 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "anyhow" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64ct" +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 = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "byte-slice-cast" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", +] + +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "tap", + "zeroize", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "bitvec", + "rand_core", + "subtle", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "impl-trait-for-tuples" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d7a9f6330b71fea57921c9b61c47ee6e84f72d394754eff6163ae67e7395eb" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "k256" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "956ff9b67e26e1a6a866cb758f12c6f8746208489e3e4a4b5580802f2f0a587b" +dependencies = [ + "cfg-if", + "ecdsa", + "elliptic-curve", + "once_cell", + "sha2", + "signature", +] + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "minimal-reth-program" +version = "0.1.0" +dependencies = [ + "sp1-zkvm", +] + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "parity-scale-codec" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" +dependencies = [ + "arrayvec", + "byte-slice-cast", + "impl-trait-for-tuples", + "parity-scale-codec-derive", +] + +[[package]] +name = "parity-scale-codec-derive" +version = "3.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "scale-info" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" +dependencies = [ + "cfg-if", + "derive_more", + "parity-scale-codec", + "scale-info-derive", +] + +[[package]] +name = "scale-info-derive" +version = "2.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "serde" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.201" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.63", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "snowbridge-amcl" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460a9ed63cdf03c1b9847e8a12a5f5ba19c4efd5869e4a737e05be25d7c427e5" +dependencies = [ + "parity-scale-codec", + "scale-info", +] + +[[package]] +name = "sp1-precompiles" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +dependencies = [ + "anyhow", + "bincode", + "cfg-if", + "getrandom", + "hex", + "k256", + "num", + "rand", + "serde", + "snowbridge-amcl", +] + +[[package]] +name = "sp1-zkvm" +version = "0.1.0" +source = "git+https://github.com/succinctlabs/sp1.git#2f57e1e77f7c88396b571bd961d3cbe4b1291c7a" +dependencies = [ + "bincode", + "cfg-if", + "getrandom", + "k256", + "libm", + "once_cell", + "rand", + "serde", + "sha2", + "sp1-precompiles", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5be731623ca1a1fb7d8be6f261a3be6d3e2337b8a1f97be944d020c8fcb704" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/testing/zkevm-lib/Cargo.toml b/testing/zkevm-lib/Cargo.toml new file mode 100644 index 000000000000..e356d401bba3 --- /dev/null +++ b/testing/zkevm-lib/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "zkevm-lib" +description = "Library methods that will be used in the zkEVM" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +homepage.workspace = true +repository.workspace = true + +[lints] +workspace = true + +[dependencies] +reth-primitives = { path = "../../crates/primitives", default-features = false, features = ["alloy-compat"]} +reth-consensus.workspace = true +reth-interfaces = { path = "../../crates/interfaces", default-features = false } +reth-evm.workspace = true +revm.workspace = true +reth-revm.workspace = true +reth-node-ethereum.workspace = true +revm-primitives.workspace = true +eyre.workspace = true +serde_json.workspace = true +reth-trie.workspace = true +serde.workspace = true \ No newline at end of file diff --git a/testing/zkevm-lib/README.md b/testing/zkevm-lib/README.md new file mode 100644 index 000000000000..2a0ded0a66d4 --- /dev/null +++ b/testing/zkevm-lib/README.md @@ -0,0 +1,5 @@ +To run testing on a zkVM, you must run on a Linux machine. + +First run `bash install.sh` to download the `riscv-gcc-prebuilt` toolchain. Note that this toolchain is only prebuilt for Linux machines, which is why you're required to use Linux. + +Then, run `bash compile.sh` which will compile with this directory's `Cargo.toml` to the SP1 zkVM. If compilation succeeds, then this means we can use all of those crates within any program written for SP1. \ No newline at end of file diff --git a/testing/zkevm-lib/src/lib.rs b/testing/zkevm-lib/src/lib.rs new file mode 100644 index 000000000000..157e9d587799 --- /dev/null +++ b/testing/zkevm-lib/src/lib.rs @@ -0,0 +1,93 @@ +//! A simple script that has takes in a block & RPC, fetches the block. +pub mod witness; + +use crate::witness::WitnessDb; + +use eyre::Ok; +use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; +use reth_interfaces::executor::BlockValidationError; +use reth_primitives::{ + trie::AccountProof, Address, Block as RethBlock, ChainSpecBuilder, Receipts, B256, MAINNET, +}; +// use reth_provider::BundleStateWithReceipts; +use revm::db::CacheDB; +use revm_primitives::{keccak256, Bytecode, HashMap, U256}; + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +/// A struct that holds the input for a zkVM program to execute a block. +pub struct SP1Input { + /// The previous block. + pub prev_block: RethBlock, + /// The block that will be executed inside the zkVM program. + pub block: RethBlock, + /// Address to merkle proofs. + pub address_to_proof: HashMap, + /// Block number to block hash. + pub block_hashes: HashMap, +} + +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct FullAccountProof { + pub account_proof: AccountProof, + pub code: Bytecode, +} + +impl FullAccountProof { + fn verify(&self, state_root: B256) -> eyre::Result<()> { + self.account_proof.verify(state_root)?; + // Assert that the code hash matches the code. + // TODO: there is an optimization for EMPTY_CODE_HASH If the self.code is empty. + let code_hash = keccak256(self.code.bytes()); + if self.account_proof.info.unwrap().bytecode_hash.unwrap() != code_hash { + return Err(eyre::eyre!("Code hash does not match the code")); + } + Ok(()) + } +} + +impl SP1Input { + /// Program that verifies the STF, run inside the zkVM. + /// TODO: this should perhaps be a functoin on SP1Input. + pub fn verify_stf(&self) -> eyre::Result<()> { + let chain_spec = ChainSpecBuilder::default() + .chain(MAINNET.chain) + .genesis( + serde_json::from_str(include_str!( + "../../../crates/ethereum/node/tests/assets/genesis.json" + )) + .unwrap(), + ) + .shanghai_activated() + .build(); + let block = self.block.clone(); + let merkle_block_td = U256::from(0); // TODO: this should be an input? + + println!("Instantiating WitnessDb from SP1Input..."); + let witness_db_inner = WitnessDb::new(self.clone()); + let witness_db = CacheDB::new(witness_db_inner); + println!("Executing block with witness db..."); + + // TODO: can we import `EthExecutorProvider` from reth-evm instead of reth-node-ethereum? + let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) + .executor(witness_db); + let BlockExecutionOutput { state, receipts, .. } = executor.execute( + ( + &block + .clone() + .with_recovered_senders() + .ok_or(BlockValidationError::SenderRecoveryError)?, + (merkle_block_td + block.header.difficulty).into(), + ) + .into(), + )?; + println!("Done processing block!"); + // let block_state = BundleStateWithReceipts::new( + // state, + // Receipts::from_block_receipt(receipts), + // block.header.number, + // ); + + // TODO: either return or verify the resulting state root. + Ok(()) + } +} diff --git a/testing/zkvm-script/src/witness.rs b/testing/zkevm-lib/src/witness.rs similarity index 95% rename from testing/zkvm-script/src/witness.rs rename to testing/zkevm-lib/src/witness.rs index 1e67ee1677d1..76ebdab655eb 100644 --- a/testing/zkvm-script/src/witness.rs +++ b/testing/zkevm-lib/src/witness.rs @@ -1,10 +1,10 @@ use crate::SP1Input; +use reth_interfaces::provider::ProviderError; use reth_primitives::B256; -use reth_provider::ProviderError; use revm::DatabaseRef; use revm_primitives::{AccountInfo, Address, Bytecode, HashMap, U256}; -pub(crate) struct WitnessDb { +pub struct WitnessDb { pub address_to_account_info: HashMap, pub address_to_storage: HashMap>, pub block_hashes: HashMap, @@ -12,7 +12,7 @@ pub(crate) struct WitnessDb { } impl WitnessDb { - pub(crate) fn new(sp1_input: SP1Input) -> Self { + pub fn new(sp1_input: SP1Input) -> Self { let state_root: B256 = sp1_input.prev_block.state_root.into(); let mut address_to_account_info = HashMap::new(); let mut address_to_storage = HashMap::new(); diff --git a/testing/zkvm-script/Cargo.toml b/testing/zkvm-script/Cargo.toml index ff2ade6c1d98..80eab859402c 100644 --- a/testing/zkvm-script/Cargo.toml +++ b/testing/zkvm-script/Cargo.toml @@ -35,4 +35,6 @@ ethers-providers = "2.0.14" alloy-transport = "0.0.0-reserved" async-std = "1.12.0" futures.workspace = true -serde.workspace = true \ No newline at end of file +serde.workspace = true +zkevm-lib = { path = "../zkevm-lib"} +sp1-sdk = { git = "https://github.com/succinctlabs/sp1", brain = "main" } \ No newline at end of file diff --git a/testing/zkvm-script/src/main.rs b/testing/zkvm-script/src/main.rs index b2b535d1f485..5213e14be3e5 100644 --- a/testing/zkvm-script/src/main.rs +++ b/testing/zkvm-script/src/main.rs @@ -1,12 +1,15 @@ //! A simple script that has takes in a block & RPC, fetches the block. pub mod cache; pub mod provider_db; -pub mod witness; +// pub mod witness; -use crate::{cache::CachedProvider, provider_db::RpcDb, witness::WitnessDb}; +pub use zkevm_lib::FullAccountProof; +use zkevm_lib::{witness::WitnessDb, SP1Input}; + +use crate::{cache::CachedProvider, provider_db::RpcDb}; use alloy_primitives::Bytes; -use alloy_provider::Provider; +use alloy_provider::{Provider, Provider as AlloyProvider, ReqwestProvider}; use alloy_rlp::{Decodable, Encodable}; use eyre::Ok; use reth_evm::execute::{BlockExecutionOutput, BlockExecutorProvider, Executor}; @@ -23,44 +26,12 @@ use reth_provider::BundleStateWithReceipts; use reth_trie::{HashedPostState, HashedStorage}; use revm::db::CacheDB; use revm_primitives::{keccak256, Bytecode, HashMap, U256}; +use sp1_sdk::{utils, ProverClient, SP1Stdin}; use url::Url; -#[derive(Debug, Clone)] -/// A struct that holds the input for a zkVM program to execute a block. -pub struct SP1Input { - /// The previous block. - pub prev_block: RethBlock, - /// The block that will be executed inside the zkVM program. - pub block: RethBlock, - /// Address to merkle proofs. - pub address_to_proof: HashMap, - /// Block number to block hash. - pub block_hashes: HashMap, -} - -#[derive(Debug, Clone)] -pub struct FullAccountProof { - account_proof: AccountProof, - code: Bytecode, -} - -impl FullAccountProof { - fn verify(&self, state_root: B256) -> eyre::Result<()> { - self.account_proof.verify(state_root)?; - // Assert that the code hash matches the code. - // TODO: there is an optimization for EMPTY_CODE_HASH If the self.code is empty. - let code_hash = keccak256(self.code.bytes()); - if self.account_proof.info.unwrap().bytecode_hash.unwrap() != code_hash { - return Err(eyre::eyre!("Code hash does not match the code")); - } - Ok(()) - } -} +const ELF: &[u8] = include_bytes!("../../zkvm/elf/riscv32im-succinct-zkvm-elf"); async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { - // We put imports here that are not used in the zkVM program. - use alloy_provider::{Provider as AlloyProvider, ReqwestProvider}; - // Initialize a provider. let provider = ReqwestProvider::new_http(rpc_url); let merkle_block_td = U256::ZERO; @@ -130,7 +101,10 @@ async fn get_input(block_number: u64, rpc_url: Url) -> eyre::Result { // let (in_memory_state_root, in_memory_updates) = // block_state.hash_state_slow().state_root_with_updates(provider.tx_ref())?; - let _state_root = update_state_root(&provider_db, &block_state).await?; + // let state_root = update_state_root(&provider_db, &block_state).await?; + // println!("state_root {:?}", state_root); + // println!("block.header.state_root {:?}", block.header.state_root); + // assert_eq!(state_root, block.header.state_root); // TODO: check that the computed state_root matches the next_block.header.state_root @@ -179,7 +153,7 @@ async fn update_state_root( // TODO: calls should be parallelized let proof = provider_db .provider - .get_proof(*account_reverse_lookup.get(&hashed_address).unwrap(), storage_keys.clone()) + .(get_proof)(*account_reverse_lookup.get(&hashed_address).unwrap(), storage_keys.clone()) .await?; let storage_root = if proof.storage_proof.is_empty() { @@ -293,59 +267,48 @@ fn update_hash_builder_from_proof( Ok(()) } -/// Program that verifies the STF, run inside the zkVM. -fn verify_stf(sp1_input: SP1Input) -> eyre::Result<()> { - let chain_spec = ChainSpecBuilder::default() - .chain(MAINNET.chain) - .genesis( - serde_json::from_str(include_str!( - "../../../crates/ethereum/node/tests/assets/genesis.json" - )) - .unwrap(), - ) - .shanghai_activated() - .build(); - let block = sp1_input.block.clone(); - let merkle_block_td = U256::from(0); // TODO: this should be an input? +#[tokio::main] +async fn main() { + // Setup logging. + utils::setup_logger(); - println!("Instantiating WitnessDb from SP1Input..."); - let witness_db_inner = WitnessDb::new(sp1_input.clone()); - let witness_db = CacheDB::new(witness_db_inner); - println!("Executing block with witness db..."); + let block_number = 18884864u64; + let file_path = format!("sp1_input_{}.json", block_number); + + let sp1_input: Sp1Input; + + if fs::try_exists(&file_path).await? { + // If the file path exists, then load sp1_input from the file. + let content = fs::read_to_string(&file_path).await?; + sp1_input = serde_json::from_str(&content)?; + } else { + // Otherwise, generate the sp1_input from the block by executing it. + let rpc_url = + Url::parse("https://eth-mainnet.g.alchemy.com/v2/hIxcf_hqT9It2hS8iCFeHKklL8tNyXNF") + .expect("Invalid RPC URL"); + println!("Fetching block number {} from {}", block_number, rpc_url); + + // Get the input. + sp1_input = get_input(block_number, rpc_url).await.expect("Failed to get input"); + + // Save the input to a file. + let serialized_input = serde_json::to_string(&sp1_input)?; + let mut file = File::create(&file_path).await?; + file.write_all(serialized_input.as_bytes()).await?; + } - // TODO: can we import `EthExecutorProvider` from reth-evm instead of reth-node-ethereum? - let executor = reth_node_ethereum::EthExecutorProvider::ethereum(chain_spec.clone().into()) - .executor(witness_db); - let BlockExecutionOutput { state, receipts, .. } = executor.execute( - ( - &block - .clone() - .with_recovered_senders() - .ok_or(BlockValidationError::SenderRecoveryError)?, - (merkle_block_td + block.header.difficulty).into(), - ) - .into(), - )?; - println!("Done processing block!"); - let block_state = BundleStateWithReceipts::new( - state, - Receipts::from_block_receipt(receipts), - block.header.number, - ); + // Verify the STF using SP1_input + sp1_input.verify_stf().expect("Failed to verify STF"); - // TODO: either return or verify the resulting state root. - Ok(()) -} + // Now generate the proof. + let mut stdin = SP1Stdin::new(); + stdin.write(&n); -#[tokio::main] -async fn main() { - let block_number = 18884864u64; - let rpc_url = - Url::parse("https://eth-mainnet.g.alchemy.com/v2/hIxcf_hqT9It2hS8iCFeHKklL8tNyXNF") - .expect("Invalid RPC URL"); - println!("Fetching block number {} from {}", block_number, rpc_url); - // Get the input. - let sp1_input = get_input(block_number, rpc_url).await.expect("Failed to get input"); - // Verify the STF. - verify_stf(sp1_input).expect("Failed to verify STF"); + // Generate the proof for the given program and input. + let client = ProverClient::new(); + let (pk, vk) = client.setup(ELF); + let mut proof = client.prove(&pk, stdin).unwrap(); + println!("generated proof"); + // Verify proof and public values + client.verify_compressed(&proof, &vk).expect("verification failed"); } diff --git a/testing/zkvm-script/src/provider_db.rs b/testing/zkvm-script/src/provider_db.rs index 679d39417688..ac91e08b7918 100644 --- a/testing/zkvm-script/src/provider_db.rs +++ b/testing/zkvm-script/src/provider_db.rs @@ -13,7 +13,7 @@ use revm_primitives::{AccountInfo, Bytecode, HashMap, HashSet}; use crate::{FullAccountProof, RethBlock, SP1Input}; -fn convert_proof(proof: EIP1186AccountProofResponse) -> AccountProof { +pub fn convert_proof(proof: EIP1186AccountProofResponse) -> AccountProof { let address = proof.address; let balance = proof.balance; let code_hash = proof.code_hash; diff --git a/testing/zkvm/Cargo.toml b/testing/zkvm/Cargo.toml index 547ec1d00862..88de9c7a7a53 100644 --- a/testing/zkvm/Cargo.toml +++ b/testing/zkvm/Cargo.toml @@ -14,6 +14,7 @@ workspace = true [dependencies] sp1-zkvm = { git = "https://github.com/succinctlabs/sp1.git", rev = "v1.0.0-testnet" } reth-primitives.workspace = true -reth-consensus.workspace = true -reth-interfaces.workspace = true -reth-evm.workspace = true \ No newline at end of file +# reth-consensus.workspace = true +# reth-interfaces.workspace = true +# reth-evm.workspace = true +# zkevm-lib = { path = "../zkevm-lib" } \ No newline at end of file diff --git a/testing/zkvm/src/main.rs b/testing/zkvm/src/main.rs index d4208a599b78..1153c7ca9cfa 100644 --- a/testing/zkvm/src/main.rs +++ b/testing/zkvm/src/main.rs @@ -3,5 +3,10 @@ #![no_main] sp1_zkvm::entrypoint!(main); +// use zkevm_lib::SP1Input; + /// The main entrypoint for the zkVM program. -pub fn main() {} +pub fn main() { + // let sp1_input = sp1_zkvm::io::read::(); + // sp1_input.verify_stf().expect("Failed to verify STF"); +}