From 8d9fd64b11bcd1fa2e453d5dcd671e9eebe54ef8 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Wed, 7 Jun 2023 15:26:28 -0700 Subject: [PATCH 01/19] chore: update dependencies --- snark-verifier/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index ecf3c6bb..81248a2d 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -14,7 +14,7 @@ rand = "0.8" serde = { version = "1.0", features = ["derive"] } # Use halo2-base as non-optional dependency because it re-exports halo2_proofs, halo2curves, and poseidon, using different repos based on feature flag "halo2-axiom" or "halo2-pse" -halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "release-0.3.0", default-features = false } +halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } # This is Scroll's audited poseidon circuit. We only use it for the Native Poseidon spec. We do not use the halo2 circuit at all (and it wouldn't even work because the halo2_proofs tag is not compatbile). poseidon-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit.git" } @@ -29,7 +29,7 @@ rlp = { version = "0.5.2", default-features = false, features = ["std"], optiona revm = { version = "= 2.3.1", optional = true } # loader_halo2 -halo2-ecc = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "release-0.3.0", default-features = false, optional = true } +halo2-ecc = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false, optional = true } [dev-dependencies] ark-std = { version = "0.3.0", features = ["print-trace"] } @@ -61,4 +61,4 @@ required-features = ["loader_halo2", "loader_evm"] [[example]] name = "recursion" -required-features = ["loader_halo2"] \ No newline at end of file +required-features = ["loader_halo2"] From 4c4e9e0c9f89fbbbeb8e26cab93bf5cdb9e95684 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Fri, 7 Jul 2023 01:00:30 -0700 Subject: [PATCH 02/19] Minor: merge v0.1.1 to develop (#21) Just cargo fixes --- Cargo.lock | 4695 --------------------------------- snark-verifier-sdk/Cargo.toml | 4 +- snark-verifier/Cargo.toml | 8 +- 3 files changed, 6 insertions(+), 4701 deletions(-) delete mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 0597252a..00000000 --- a/Cargo.lock +++ /dev/null @@ -1,4695 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aes" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", - "opaque-debug 0.3.0", -] - -[[package]] -name = "ahash" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" -dependencies = [ - "cfg-if", - "getrandom", - "once_cell", - "version_check", -] - -[[package]] -name = "aho-corasick" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" -dependencies = [ - "memchr", -] - -[[package]] -name = "android_system_properties" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" -dependencies = [ - "libc", -] - -[[package]] -name = "anes" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" - -[[package]] -name = "ark-std" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "colored", - "num-traits", - "rand", -] - -[[package]] -name = "array-init" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" - -[[package]] -name = "arrayref" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" - -[[package]] -name = "arrayvec" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" - -[[package]] -name = "async-trait" -version = "0.1.68" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", -] - -[[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", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - -[[package]] -name = "auto_impl" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fee3da8ef1276b0bee5dd1c7258010d8fffd31801447323115a25560e1327b89" -dependencies = [ - "proc-macro-error", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base16ct" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce" - -[[package]] -name = "base58" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83" - -[[package]] -name = "base58check" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee2fe4c9a0c84515f136aaae2466744a721af6d63339c18689d9e995d74d99b" -dependencies = [ - "base58", - "sha2 0.8.2", -] - -[[package]] -name = "base64" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - -[[package]] -name = "base64" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105" - -[[package]] -name = "base64ct" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a32fd6af2b5827bce66c29053ba0e7c42b9dcab01835835058558c10851a46b" - -[[package]] -name = "bech32" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dabbe35f96fb9507f7330793dc490461b2962659ac5d427181e451a623751d1" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitvec" -version = "0.17.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41262f11d771fd4a61aa3ce019fca363b4b6c282fca9da2a31186d3965a47a5c" -dependencies = [ - "either", - "radium 0.3.0", -] - -[[package]] -name = "bitvec" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" -dependencies = [ - "funty", - "radium 0.7.0", - "tap", - "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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c2f0dc9a68c6317d884f97cc36cf5a3d20ba14ce404227df55e1af708ab04bc" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - -[[package]] -name = "block-buffer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a076c298b9ecdb530ed9d967e74a6027d6a7478924520acddcddc24c1c8ab3ab" -dependencies = [ - "arrayref", - "byte-tools 0.2.0", -] - -[[package]] -name = "block-buffer" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -dependencies = [ - "block-padding 0.1.5", - "byte-tools 0.3.1", - "byteorder", - "generic-array 0.12.4", -] - -[[package]] -name = "block-buffer" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" -dependencies = [ - "block-padding 0.2.1", - "generic-array 0.14.7", -] - -[[package]] -name = "block-buffer" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools 0.3.1", -] - -[[package]] -name = "block-padding" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" - -[[package]] -name = "borsh" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b" -dependencies = [ - "borsh-derive", - "hashbrown 0.13.2", -] - -[[package]] -name = "borsh-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0754613691538d51f329cce9af41d7b7ca150bc973056f1156611489475f54f7" -dependencies = [ - "borsh-derive-internal", - "borsh-schema-derive-internal", - "proc-macro-crate 0.1.5", - "proc-macro2", - "syn 1.0.109", -] - -[[package]] -name = "borsh-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb438156919598d2c7bad7e1c0adf3d26ed3840dbc010db1a882a65583ca2fb" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "borsh-schema-derive-internal" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634205cc43f74a1b9046ef87c4540ebda95696ec0f315024860cad7c5b0f5ccd" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bs58" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771fe0050b883fcc3ea2359b1a96bcfbc090b7116eae7c3c512c7a083fdf23d3" - -[[package]] -name = "bumpalo" -version = "3.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" - -[[package]] -name = "bus-mapping" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/zkevm-circuits.git?rev=f834e61#f834e61ed2937adfecbb5fdad9cab711871c27ac" -dependencies = [ - "eth-types", - "ethers-core", - "ethers-providers", - "gadgets", - "halo2_proofs 0.2.0 (git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02)", - "itertools", - "keccak256", - "lazy_static", - "log", - "serde", - "serde_json", - "strum", - "strum_macros", -] - -[[package]] -name = "byte-slice-cast" -version = "1.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" - -[[package]] -name = "byte-tools" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" - -[[package]] -name = "bytecheck" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b6372023ac861f6e6dc89c8344a8f398fb42aaba2b5dbc649ca0c0e9dbcb627" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ec4c6f261935ad534c0c22dbef2201b45918860eb1c574b972bd213a76af61" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "bytemuck" -version = "1.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "bytes" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" -dependencies = [ - "serde", -] - -[[package]] -name = "cassowary" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "chrono" -version = "0.4.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b" -dependencies = [ - "iana-time-zone", - "num-integer", - "num-traits", - "serde", - "winapi", -] - -[[package]] -name = "ciborium" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" - -[[package]] -name = "ciborium-ll" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "cipher" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "clap" -version = "3.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" -dependencies = [ - "bitflags", - "clap_lex", - "indexmap", - "textwrap", -] - -[[package]] -name = "clap_lex" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" -dependencies = [ - "os_str_bytes", -] - -[[package]] -name = "coins-bip32" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634c509653de24b439672164bbf56f5f582a2ab0e313d3b0f6af0b7345cf2560" -dependencies = [ - "bincode", - "bs58", - "coins-core", - "digest 0.10.7", - "getrandom", - "hmac 0.12.1", - "k256", - "lazy_static", - "serde", - "sha2 0.10.6", - "thiserror", -] - -[[package]] -name = "coins-bip39" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a11892bcac83b4c6e95ab84b5b06c76d9d70ad73548dd07418269c5c7977171" -dependencies = [ - "bitvec 0.17.4", - "coins-bip32", - "getrandom", - "hex", - "hmac 0.12.1", - "pbkdf2 0.11.0", - "rand", - "sha2 0.10.6", - "thiserror", -] - -[[package]] -name = "coins-core" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94090a6663f224feae66ab01e41a2555a8296ee07b5f20dab8888bdefc9f617" -dependencies = [ - "base58check", - "base64 0.12.3", - "bech32", - "blake2", - "digest 0.10.7", - "generic-array 0.14.7", - "hex", - "ripemd", - "serde", - "serde_derive", - "sha2 0.10.6", - "sha3 0.10.8", - "thiserror", -] - -[[package]] -name = "colored" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd" -dependencies = [ - "atty", - "lazy_static", - "winapi", -] - -[[package]] -name = "const-oid" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913" - -[[package]] -name = "constant_time_eq" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" - -[[package]] -name = "convert_case" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8" - -[[package]] -name = "core-foundation-sys" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" - -[[package]] -name = "cpp_demangle" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c76f98bdfc7f66172e6c7065f981ebb576ffc903fe4c0561d9f0c2509226dc6" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "cpufeatures" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" -dependencies = [ - "libc", -] - -[[package]] -name = "criterion" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c76e09c1aae2bc52b3d2f29e13c6572553b30c4aa1b8a49fd70de6412654cb" -dependencies = [ - "anes", - "atty", - "cast", - "ciborium", - "clap", - "criterion-plot", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-macro" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288a8f36b28a19d7dbd572c76006c0a0eba1f3bf912a254dda211c6f665e7ffc" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "criterion-plot" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" -dependencies = [ - "cfg-if", - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crossterm" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" -dependencies = [ - "bitflags", - "crossterm_winapi", - "libc", - "mio", - "parking_lot 0.12.1", - "signal-hook", - "signal-hook-mio", - "winapi", -] - -[[package]] -name = "crossterm_winapi" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" -dependencies = [ - "winapi", -] - -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef2b4b23cddf68b89b8f8069890e8c270d54e2d5fe1b143820234805e4cb17ef" -dependencies = [ - "generic-array 0.14.7", - "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 0.14.7", - "typenum", -] - -[[package]] -name = "crypto-mac" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b584a330336237c1eecd3e94266efb216c56ed91225d634cb2991c5f3fd1aeab" -dependencies = [ - "generic-array 0.14.7", - "subtle", -] - -[[package]] -name = "ctr" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "049bb91fb4aaf0e3c7efa6cd5ef877dbbbd15b39dad06d9948de4ec8a75761ea" -dependencies = [ - "cipher", -] - -[[package]] -name = "darling" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" -dependencies = [ - "darling_core 0.13.4", - "darling_macro 0.13.4", -] - -[[package]] -name = "darling" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0558d22a7b463ed0241e993f76f09f30b126687447751a8638587b864e4b3944" -dependencies = [ - "darling_core 0.20.1", - "darling_macro 0.20.1", -] - -[[package]] -name = "darling_core" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 1.0.109", -] - -[[package]] -name = "darling_core" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab8bfa2e259f8ee1ce5e97824a3c55ec4404a0d772ca7fa96bf19f0752a046eb" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.16", -] - -[[package]] -name = "darling_macro" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" -dependencies = [ - "darling_core 0.13.4", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "darling_macro" -version = "0.20.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a358ff9f12ec09c3e61fef9b5a9902623a695a46a917b07f269bff1445611a" -dependencies = [ - "darling_core 0.20.1", - "quote", - "syn 2.0.16", -] - -[[package]] -name = "debugid" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" -dependencies = [ - "uuid 1.3.3", -] - -[[package]] -name = "der" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "digest" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" -dependencies = [ - "generic-array 0.9.1", -] - -[[package]] -name = "digest" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -dependencies = [ - "generic-array 0.12.4", -] - -[[package]] -name = "digest" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" -dependencies = [ - "generic-array 0.14.7", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "crypto-common", - "subtle", -] - -[[package]] -name = "ecc" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" -dependencies = [ - "group", - "integer", - "num-bigint", - "num-integer", - "num-traits", - "rand", - "subtle", -] - -[[package]] -name = "ecdsa" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" -dependencies = [ - "ecc", - "group", - "num-bigint", - "num-integer", - "num-traits", - "rand", - "subtle", -] - -[[package]] -name = "ecdsa" -version = "0.14.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c" -dependencies = [ - "der", - "elliptic-curve", - "rfc6979", - "signature", -] - -[[package]] -name = "either" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" - -[[package]] -name = "elliptic-curve" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3" -dependencies = [ - "base16ct", - "crypto-bigint", - "der", - "digest 0.10.7", - "ff", - "generic-array 0.14.7", - "group", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", -] - -[[package]] -name = "encoding_rs" -version = "0.8.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "env_logger" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" -dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", -] - -[[package]] -name = "errno" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "eth-keystore" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f65b750ac950f2f825b36d08bef4cda4112e19a7b1a68f6e2bb499413e12440" -dependencies = [ - "aes", - "ctr", - "digest 0.10.7", - "hex", - "hmac 0.12.1", - "pbkdf2 0.11.0", - "rand", - "scrypt", - "serde", - "serde_json", - "sha2 0.10.6", - "sha3 0.10.8", - "thiserror", - "uuid 0.8.2", -] - -[[package]] -name = "eth-types" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/zkevm-circuits.git?rev=f834e61#f834e61ed2937adfecbb5fdad9cab711871c27ac" -dependencies = [ - "ethers-core", - "ethers-signers", - "halo2_proofs 0.2.0 (git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02)", - "hex", - "itertools", - "lazy_static", - "libsecp256k1", - "num", - "num-bigint", - "regex", - "serde", - "serde_json", - "serde_with 1.14.0", - "sha3 0.10.8", - "strum", - "strum_macros", - "subtle", - "uint", -] - -[[package]] -name = "ethabi" -version = "17.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4966fba78396ff92db3b817ee71143eccd98acf0f876b8d600e585a670c5d1b" -dependencies = [ - "ethereum-types 0.13.1", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3 0.10.8", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11da94e443c60508eb62cf256243a64da87304c2802ac2528847f79d750007ef" -dependencies = [ - "crunchy", - "fixed-hash 0.7.0", - "impl-rlp", - "impl-serde", - "tiny-keccak", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash 0.8.0", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2827b94c556145446fcce834ca86b7abf0c39a805883fe20e72c5bfdb5a0dc6" -dependencies = [ - "ethbloom 0.12.1", - "fixed-hash 0.7.0", - "impl-rlp", - "impl-serde", - "primitive-types 0.11.1", - "uint", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom 0.13.0", - "fixed-hash 0.8.0", - "primitive-types 0.12.1", - "uint", -] - -[[package]] -name = "ethers-core" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ebdd63c828f58aa067f40f9adcbea5e114fb1f90144b3a1e2858e0c9b1ff4e8" -dependencies = [ - "arrayvec", - "bytes", - "chrono", - "convert_case", - "elliptic-curve", - "ethabi", - "fastrlp", - "generic-array 0.14.7", - "hex", - "k256", - "proc-macro2", - "rand", - "rlp", - "rlp-derive", - "rust_decimal", - "serde", - "serde_json", - "strum", - "syn 1.0.109", - "thiserror", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "ethers-providers" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46482e4d1e79b20c338fd9db9e166184eb387f0a4e7c05c5b5c0aa2e8c8900c" -dependencies = [ - "async-trait", - "auto_impl", - "base64 0.13.1", - "ethers-core", - "futures-channel", - "futures-core", - "futures-timer", - "futures-util", - "getrandom", - "hashers", - "hex", - "http", - "once_cell", - "parking_lot 0.11.2", - "pin-project", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tokio-tungstenite", - "tracing", - "tracing-futures", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-timer", - "web-sys", - "ws_stream_wasm", -] - -[[package]] -name = "ethers-signers" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73a72ecad124e8ccd18d6a43624208cab0199e59621b1f0fa6b776b2e0529107" -dependencies = [ - "async-trait", - "coins-bip32", - "coins-bip39", - "elliptic-curve", - "eth-keystore", - "ethers-core", - "hex", - "rand", - "sha2 0.10.6", - "thiserror", -] - -[[package]] -name = "external-tracer" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/zkevm-circuits.git?rev=f834e61#f834e61ed2937adfecbb5fdad9cab711871c27ac" -dependencies = [ - "eth-types", - "geth-utils", - "serde", - "serde_json", -] - -[[package]] -name = "fake-simd" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fastrlp" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "089263294bb1c38ac73649a6ad563dd9a5142c8dc0482be15b8b9acb22a1611e" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types 0.13.1", - "fastrlp-derive", -] - -[[package]] -name = "fastrlp-derive" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0f9d074ab623d1b388c12544bfeed759c7df36dc5c300cda053df9ba1232075" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ff" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d013fc25338cc558c5c2cfbad646908fb23591e2404481826742b651c9af7160" -dependencies = [ - "bitvec 1.0.1", - "rand_core", - "subtle", -] - -[[package]] -name = "findshlibs" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9e59cd0f7e0806cca4be089683ecb6434e602038df21fe6bf6711b2f07f64" -dependencies = [ - "cc", - "lazy_static", - "libc", - "winapi", -] - -[[package]] -name = "fixed-hash" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcf0ed7fe52a17a03854ec54a9f76d6d84508d1c0e66bc1793301c73fc8493c" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fixed-hash" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835c052cb0c08c1acf6ffd71c022172e18723949c8282f2b9f27efbc51e64534" -dependencies = [ - "byteorder", - "rand", - "rustc-hex", - "static_assertions", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "form_urlencoded" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" -dependencies = [ - "percent-encoding", -] - -[[package]] -name = "funty" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" - -[[package]] -name = "futures" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-executor" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-io" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" - -[[package]] -name = "futures-macro" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", -] - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-timer" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "pin-utils", - "slab", -] - -[[package]] -name = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "gadgets" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/zkevm-circuits.git?rev=f834e61#f834e61ed2937adfecbb5fdad9cab711871c27ac" -dependencies = [ - "digest 0.7.6", - "eth-types", - "halo2_proofs 0.2.0 (git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02)", - "sha3 0.7.3", - "strum", -] - -[[package]] -name = "generic-array" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d00328cedcac5e81c683e5620ca6a30756fc23027ebf9bff405c0e8da1fbb7e" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "geth-utils" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/zkevm-circuits.git?rev=f834e61#f834e61ed2937adfecbb5fdad9cab711871c27ac" -dependencies = [ - "env_logger", - "gobuild", - "log", -] - -[[package]] -name = "getrandom" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", -] - -[[package]] -name = "gimli" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" - -[[package]] -name = "gobuild" -version = "0.1.0-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e156a4ddbf3deb5e8116946c111413bd9a5679bdc1536c78a60618a7a9ac9e" -dependencies = [ - "cc", -] - -[[package]] -name = "group" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "halo2-base" -version = "0.3.0" -source = "git+https://github.com/axiom-crypto/halo2-lib.git?branch=release-0.3.0#238b89e7562d52166c1e08154b7c9759f65322a6" -dependencies = [ - "ff", - "halo2_proofs 0.2.0", - "halo2_proofs 0.2.0 (git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02)", - "itertools", - "jemallocator", - "log", - "num-bigint", - "num-integer", - "num-traits", - "rand_chacha", - "rayon", - "rustc-hash", - "serde", - "serde_json", -] - -[[package]] -name = "halo2-ecc" -version = "0.3.0" -source = "git+https://github.com/axiom-crypto/halo2-lib.git?branch=release-0.3.0#238b89e7562d52166c1e08154b7c9759f65322a6" -dependencies = [ - "ff", - "group", - "halo2-base", - "itertools", - "num-bigint", - "num-integer", - "num-traits", - "rand", - "rand_chacha", - "rand_core", - "rayon", - "serde", - "serde_json", -] - -[[package]] -name = "halo2_proofs" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e925780549adee8364c7f2b685c753f6f3df23bde520c67416e93bf615933760" -dependencies = [ - "blake2b_simd", - "ff", - "group", - "pasta_curves", - "rand_core", - "rayon", -] - -[[package]] -name = "halo2_proofs" -version = "0.2.0" -dependencies = [ - "blake2b_simd", - "crossbeam", - "ff", - "group", - "halo2curves 0.3.1", - "rand", - "rand_core", - "rayon", - "rustc-hash", - "sha3 0.9.1", - "tracing", -] - -[[package]] -name = "halo2_proofs" -version = "0.2.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2022_09_10#a9e99a72a65d7c98e8a4258c2c94269c834d1c10" -dependencies = [ - "blake2b_simd", - "ff", - "group", - "halo2curves 0.2.1 (git+https://github.com/privacy-scaling-explorations/halo2curves?tag=0.2.1)", - "rand_core", - "rayon", - "tracing", -] - -[[package]] -name = "halo2_proofs" -version = "0.2.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02#0a8646b78286a13d320759b1c585262d6536dce4" -dependencies = [ - "blake2b_simd", - "ff", - "group", - "halo2curves 0.3.1 (git+https://github.com/privacy-scaling-explorations/halo2curves.git?tag=0.3.1)", - "rand_core", - "rayon", - "sha3 0.9.1", - "tracing", -] - -[[package]] -name = "halo2curves" -version = "0.2.1" -source = "git+https://github.com/privacy-scaling-explorations/halo2curves?tag=0.2.1#f75ed26c961179186e9cec02cc3f841ca9e3fec1" -dependencies = [ - "ff", - "group", - "lazy_static", - "num-bigint", - "num-traits", - "pasta_curves", - "rand", - "rand_core", - "static_assertions", - "subtle", -] - -[[package]] -name = "halo2curves" -version = "0.2.1" -source = "git+https://github.com/privacy-scaling-explorations/halo2curves?tag=0.3.0#83c72d49762343ffc9576ca11a2aa615efe1029b" -dependencies = [ - "ff", - "group", - "lazy_static", - "num-bigint", - "num-traits", - "pasta_curves", - "rand", - "rand_core", - "static_assertions", - "subtle", -] - -[[package]] -name = "halo2curves" -version = "0.3.1" -dependencies = [ - "ff", - "group", - "lazy_static", - "num-bigint", - "num-traits", - "pasta_curves", - "rand", - "rand_core", - "serde", - "static_assertions", - "subtle", -] - -[[package]] -name = "halo2curves" -version = "0.3.1" -source = "git+https://github.com/privacy-scaling-explorations/halo2curves.git?tag=0.3.1#9b67e19bca30a35208b0c1b41c1723771e2c9f49" -dependencies = [ - "ff", - "group", - "lazy_static", - "num-bigint", - "num-traits", - "pasta_curves", - "rand", - "rand_core", - "static_assertions", - "subtle", -] - -[[package]] -name = "halo2wrong" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" -dependencies = [ - "group", - "halo2_proofs 0.2.0 (git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02)", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.6", -] - -[[package]] -name = "hashbrown" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" -dependencies = [ - "ahash 0.8.3", -] - -[[package]] -name = "hashers" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2bca93b15ea5a746f220e56587f71e73c6165eab783df9e26590069953e3c30" -dependencies = [ - "fxhash", -] - -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hmac" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126888268dcc288495a26bf004b38c5fdbb31682f992c84ceb046a1f0fe38840" -dependencies = [ - "crypto-mac", - "digest 0.9.0", -] - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "hmac-drbg" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ea0a1394df5b6574da6e0c1ade9e78868c9fb0a4e5ef4428e32da4676b85b1" -dependencies = [ - "digest 0.9.0", - "generic-array 0.14.7", - "hmac 0.8.1", -] - -[[package]] -name = "http" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" -dependencies = [ - "bytes", - "fnv", - "itoa", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" - -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - -[[package]] -name = "hyper" -version = "0.14.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7" -dependencies = [ - "http", - "hyper", - "rustls 0.21.1", - "tokio", - "tokio-rustls 0.24.0", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.56" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "impl-codec" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba6a270039626615617f3f36d15fc827041df3b78c439da2cadfa47455a77f2f" -dependencies = [ - "parity-scale-codec", -] - -[[package]] -name = "impl-rlp" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28220f89297a075ddc7245cd538076ee98b01f2a9c23a53a4f1105d5a322808" -dependencies = [ - "rlp", -] - -[[package]] -name = "impl-serde" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4551f042f3438e64dbd6226b20527fc84a6e1fe65688b58746a2f53623f25f5c" -dependencies = [ - "serde", -] - -[[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 = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "inferno" -version = "0.11.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fb7c1b80a1dfa604bb4a649a5c5aeef3d913f7c520cb42b40e534e8a61bcdfc" -dependencies = [ - "ahash 0.8.3", - "indexmap", - "is-terminal", - "itoa", - "log", - "num-format", - "once_cell", - "quick-xml", - "rgb", - "str_stack", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "integer" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" -dependencies = [ - "group", - "maingate", - "num-bigint", - "num-integer", - "num-traits", - "rand", - "subtle", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "ipnet" -version = "2.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" - -[[package]] -name = "is-terminal" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f" -dependencies = [ - "hermit-abi 0.3.1", - "io-lifetimes", - "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" - -[[package]] -name = "jemalloc-sys" -version = "0.5.3+5.3.0-patched" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9bd5d616ea7ed58b571b2e209a65759664d7fb021a0819d7a790afc67e47ca1" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "jemallocator" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16c2514137880c52b0b4822b563fadd38257c1f380858addb74a400889696ea6" -dependencies = [ - "jemalloc-sys", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "k256" -version = "0.11.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72c1e0b51e7ec0a97369623508396067a486bd0cbed95a2659a4b863d28cfc8b" -dependencies = [ - "cfg-if", - "ecdsa 0.14.8", - "elliptic-curve", - "sha2 0.10.6", - "sha3 0.10.8", -] - -[[package]] -name = "keccak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "keccak256" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/zkevm-circuits.git?rev=f834e61#f834e61ed2937adfecbb5fdad9cab711871c27ac" -dependencies = [ - "env_logger", - "eth-types", - "halo2_proofs 0.1.0", - "itertools", - "lazy_static", - "log", - "num-bigint", - "num-traits", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin", -] - -[[package]] -name = "libc" -version = "0.2.144" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" - -[[package]] -name = "libsecp256k1" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b09eff1b35ed3b33b877ced3a691fc7a481919c7e29c53c906226fcf55e2a1" -dependencies = [ - "arrayref", - "base64 0.13.1", - "digest 0.9.0", - "hmac-drbg", - "libsecp256k1-core", - "libsecp256k1-gen-ecmult", - "libsecp256k1-gen-genmult", - "rand", - "serde", - "sha2 0.9.9", - "typenum", -] - -[[package]] -name = "libsecp256k1-core" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be9b9bb642d8522a44d533eab56c16c738301965504753b03ad1de3425d5451" -dependencies = [ - "crunchy", - "digest 0.9.0", - "subtle", -] - -[[package]] -name = "libsecp256k1-gen-ecmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3038c808c55c87e8a172643a7d87187fc6c4174468159cb3090659d55bcb4809" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "libsecp256k1-gen-genmult" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8d6ba2cec9eacc40e6e8ccc98931840301f1006e95647ceb2dd5c3aa06f7c" -dependencies = [ - "libsecp256k1-core", -] - -[[package]] -name = "linux-raw-sys" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" - -[[package]] -name = "lock_api" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "maingate" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/halo2wrong?tag=v2023_02_02#5905a20b62fcd9f6c269416a39c80de7ced8fb02" -dependencies = [ - "group", - "halo2wrong", - "num-bigint", - "num-integer", - "num-traits", - "rand", - "subtle", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memmap2" -version = "0.5.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" -dependencies = [ - "libc", -] - -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "miniz_oxide" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" -dependencies = [ - "libc", - "log", - "wasi", - "windows-sys 0.45.0", -] - -[[package]] -name = "mock" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/zkevm-circuits.git?rev=f834e61#f834e61ed2937adfecbb5fdad9cab711871c27ac" -dependencies = [ - "eth-types", - "ethers-core", - "ethers-signers", - "external-tracer", - "itertools", - "lazy_static", - "rand", - "rand_chacha", -] - -[[package]] -name = "nix" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" -dependencies = [ - "bitflags", - "cfg-if", - "libc", - "static_assertions", -] - -[[package]] -name = "num" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", - "rand", -] - -[[package]] -name = "num-complex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e0d21255c828d6f128a1e41534206671e8c3ea0c62f32291e808dc82cff17d" -dependencies = [ - "num-traits", -] - -[[package]] -name = "num-format" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a652d9771a63711fd3c3deb670acfbe5c30a4072e664d7a3bf5a9e1056ac72c3" -dependencies = [ - "arrayvec", - "itoa", -] - -[[package]] -name = "num-integer" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-iter" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-rational" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" -dependencies = [ - "autocfg", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" -dependencies = [ - "hermit-abi 0.2.6", - "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", -] - -[[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]] -name = "object" -version = "0.30.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - -[[package]] -name = "opaque-debug" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "os_str_bytes" -version = "6.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" - -[[package]] -name = "parity-scale-codec" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ddb756ca205bd108aee3c62c6d3c994e1df84a59b9d6d4a5ea42ee1fd5a9a28" -dependencies = [ - "arrayvec", - "bitvec 1.0.1", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b26a931f824dd4eca30b3e43bb4f31cd5f0d3a403c5f5ff27106b805bfde7b" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.7", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "windows-sys 0.45.0", -] - -[[package]] -name = "password-hash" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d791538a6dcc1e7cb7fe6f6b58aca40e7f79403c45b2bc274008b5e647af1d8" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "password-hash" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7676374caaee8a325c9e7a2ae557f216c5563a171d6997b0ef8a65af35147700" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - -[[package]] -name = "pasta_curves" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc65faf8e7313b4b1fbaa9f7ca917a0eed499a9663be71477f87993604341d8" -dependencies = [ - "blake2b_simd", - "ff", - "group", - "lazy_static", - "rand", - "static_assertions", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" - -[[package]] -name = "pbkdf2" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271779f35b581956db91a3e55737327a03aa051e90b1c47aeb189508533adfd7" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", - "password-hash 0.4.2", - "sha2 0.10.6", -] - -[[package]] -name = "percent-encoding" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" - -[[package]] -name = "pharos" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" -dependencies = [ - "futures", - "rustc_version", -] - -[[package]] -name = "pin-project" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "pkcs8" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "plotters" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" - -[[package]] -name = "plotters-svg" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "poseidon" -version = "0.2.0" -source = "git+https://github.com/privacy-scaling-explorations/poseidon.git?tag=v2022_10_22#5d29df01a95e3df6334080d28e983407f56b5da3" -dependencies = [ - "group", - "halo2curves 0.2.1 (git+https://github.com/privacy-scaling-explorations/halo2curves?tag=0.3.0)", - "subtle", -] - -[[package]] -name = "poseidon-circuit" -version = "0.1.0" -source = "git+https://github.com/scroll-tech/poseidon-circuit.git#079e3f5bfc30d63ded672a97850e3c160504bfad" -dependencies = [ - "bitvec 1.0.1", - "halo2_proofs 0.2.0 (git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2022_09_10)", - "lazy_static", - "thiserror", -] - -[[package]] -name = "pprof" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "196ded5d4be535690899a4631cc9f18cdc41b7ebf24a79400f46f48e49a11059" -dependencies = [ - "backtrace", - "cfg-if", - "criterion", - "findshlibs", - "inferno", - "libc", - "log", - "nix", - "once_cell", - "parking_lot 0.12.1", - "smallvec", - "symbolic-demangle", - "tempfile", - "thiserror", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "primitive-types" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28720988bff275df1f51b171e1b2a18c30d194c4d2b61defdacecd625a5d94a" -dependencies = [ - "fixed-hash 0.7.0", - "impl-codec", - "impl-rlp", - "impl-serde", - "uint", -] - -[[package]] -name = "primitive-types" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f3486ccba82358b11a77516035647c34ba167dfa53312630de83b12bd4f3d66" -dependencies = [ - "fixed-hash 0.8.0", - "impl-codec", - "impl-rlp", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" -dependencies = [ - "toml", -] - -[[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", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "version_check", -] - -[[package]] -name = "proc-macro2" -version = "1.0.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "quick-xml" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f50b1c63b38611e7d4d7f68b82d3ad0cc71a2ad2e7f61fc10f1328d917c93cd" -dependencies = [ - "memchr", -] - -[[package]] -name = "quote" -version = "1.0.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "def50a86306165861203e7f84ecffbbdfdea79f0e51039b33de1e952358c47ac" - -[[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 = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "rayon" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78" - -[[package]] -name = "rend" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581008d2099240d37fb08d77ad713bcaec2c4d89d50b5b21a8bb1996bbab68ab" -dependencies = [ - "bytecheck", -] - -[[package]] -name = "reqwest" -version = "0.11.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55" -dependencies = [ - "base64 0.21.1", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "hyper-rustls", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls 0.21.1", - "rustls-pemfile", - "serde", - "serde_json", - "serde_urlencoded", - "tokio", - "tokio-rustls 0.24.0", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "webpki-roots", - "winreg", -] - -[[package]] -name = "revm" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73d84c8f9836efb0f5f5f8de4700a953c4e1f3119e5cfcb0aad8e5be73daf991" -dependencies = [ - "arrayref", - "auto_impl", - "bytes", - "hashbrown 0.13.2", - "num_enum", - "primitive-types 0.12.1", - "revm_precompiles", - "rlp", - "sha3 0.10.8", -] - -[[package]] -name = "revm_precompiles" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0353d456ef3e989dc9190f42c6020f09bc2025930c37895826029304413204b5" -dependencies = [ - "bytes", - "hashbrown 0.13.2", - "num", - "once_cell", - "primitive-types 0.12.1", - "ripemd", - "secp256k1", - "sha2 0.10.6", - "sha3 0.10.8", - "substrate-bn", -] - -[[package]] -name = "rfc6979" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7743f17af12fa0b03b803ba12cd6a8d9483a587e89c69445e3909655c0b9fabb" -dependencies = [ - "crypto-bigint", - "hmac 0.12.1", - "zeroize", -] - -[[package]] -name = "rgb" -version = "0.8.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ec2d3e3fc7a92ced357df9cebd5a10b6fb2aa1ee797bf7e9ce2f17dffc8f59" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "ring" -version = "0.16.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" -dependencies = [ - "cc", - "libc", - "once_cell", - "spin", - "untrusted", - "web-sys", - "winapi", -] - -[[package]] -name = "ripemd" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "rkyv" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0200c8230b013893c0b2d6213d6ec64ed2b9be2e0e016682b7224ff82cff5c58" -dependencies = [ - "bitvec 1.0.1", - "bytecheck", - "hashbrown 0.12.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid 1.3.3", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e06b915b5c230a17d7a736d1e2e63ee753c256a8614ef3f5147b13a4f5541d" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "rlp" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" -dependencies = [ - "bytes", - "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 = "rust_decimal" -version = "1.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26bd36b60561ee1fb5ec2817f198b6fd09fa571c897a5e86d1487cfc2b096dfc" -dependencies = [ - "arrayvec", - "borsh", - "bytecheck", - "byteorder", - "bytes", - "num-traits", - "rand", - "rkyv", - "serde", - "serde_json", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustc-hex" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e75f6a532d0fd9f7f13144f392b6ad56a32696bfcd9c78f797f16bbb6f072d6" - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver", -] - -[[package]] -name = "rustix" -version = "0.37.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", -] - -[[package]] -name = "rustls" -version = "0.20.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" -dependencies = [ - "log", - "ring", - "sct", - "webpki", -] - -[[package]] -name = "rustls" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e" -dependencies = [ - "log", - "ring", - "rustls-webpki", - "sct", -] - -[[package]] -name = "rustls-pemfile" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" -dependencies = [ - "base64 0.21.1", -] - -[[package]] -name = "rustls-webpki" -version = "0.100.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" - -[[package]] -name = "ryu" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" - -[[package]] -name = "salsa20" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0fbb5f676da676c260ba276a8f43a8dc67cf02d1438423aeb1c677a7212686" -dependencies = [ - "cipher", -] - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "scrypt" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e73d6d7c6311ebdbd9184ad6c4447b2f36337e327bda107d3ba9e3c374f9d325" -dependencies = [ - "hmac 0.12.1", - "password-hash 0.3.2", - "pbkdf2 0.10.1", - "salsa20", - "sha2 0.10.6", -] - -[[package]] -name = "sct" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - -[[package]] -name = "sec1" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928" -dependencies = [ - "base16ct", - "der", - "generic-array 0.14.7", - "pkcs8", - "subtle", - "zeroize", -] - -[[package]] -name = "secp256k1" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b1629c9c557ef9b293568b338dddfc8208c98a18c59d722a9d53f859d9c9b62" -dependencies = [ - "secp256k1-sys", -] - -[[package]] -name = "secp256k1-sys" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83080e2c2fc1006e625be82e5d1eb6a43b7fd9578b617fcc55814daf286bba4b" -dependencies = [ - "cc", -] - -[[package]] -name = "semver" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" - -[[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.163" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.163" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", -] - -[[package]] -name = "serde_json" -version = "1.0.96" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" -dependencies = [ - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" -dependencies = [ - "serde", - "serde_with_macros 1.5.2", -] - -[[package]] -name = "serde_with" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ff71d2c147a7b57362cead5e22f772cd52f6ab31cfcd9edcd7f6aeb2a0afbe" -dependencies = [ - "base64 0.13.1", - "chrono", - "hex", - "indexmap", - "serde", - "serde_json", - "serde_with_macros 2.3.3", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" -dependencies = [ - "darling 0.13.4", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "serde_with_macros" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881b6f881b17d13214e5d494c939ebab463d01264ce1811e9d4ac3a882e7695f" -dependencies = [ - "darling 0.20.1", - "proc-macro2", - "quote", - "syn 2.0.16", -] - -[[package]] -name = "sha-1" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a256f46ea78a0c0d9ff00077504903ac881a1dafdc20da66545699e7776b3e69" -dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug 0.2.3", -] - -[[package]] -name = "sha2" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" -dependencies = [ - "block-buffer 0.9.0", - "cfg-if", - "cpufeatures", - "digest 0.9.0", - "opaque-debug 0.3.0", -] - -[[package]] -name = "sha2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha3" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b64dcef59ed4290b9fb562b53df07f564690d6539e8ecdd4728cf392477530bc" -dependencies = [ - "block-buffer 0.3.3", - "byte-tools 0.2.0", - "digest 0.7.6", - "keccak", -] - -[[package]] -name = "sha3" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" -dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug 0.3.0", -] - -[[package]] -name = "sha3" -version = "0.10.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" -dependencies = [ - "digest 0.10.7", - "keccak", -] - -[[package]] -name = "signal-hook" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-mio" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" -dependencies = [ - "libc", - "mio", - "signal-hook", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "1.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c" -dependencies = [ - "digest 0.10.7", - "rand_core", -] - -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - -[[package]] -name = "slab" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "snark-verifier" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/snark-verifier?tag=v2023_02_02#df03d898b841f71cbc36c2fb9fa07b8196f9623e" -dependencies = [ - "ecc", - "halo2_proofs 0.2.0 (git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02)", - "halo2curves 0.3.1 (git+https://github.com/privacy-scaling-explorations/halo2curves.git?tag=0.3.1)", - "hex", - "itertools", - "lazy_static", - "num-bigint", - "num-integer", - "num-traits", - "poseidon", - "rand", -] - -[[package]] -name = "snark-verifier" -version = "0.1.1" -dependencies = [ - "ark-std", - "bytes", - "crossterm", - "halo2-base", - "halo2-ecc", - "hex", - "itertools", - "lazy_static", - "num-bigint", - "num-integer", - "num-traits", - "paste", - "poseidon-circuit", - "primitive-types 0.12.1", - "rand", - "rand_chacha", - "rayon", - "revm", - "rlp", - "serde", - "serde_json", - "sha3 0.10.8", - "tui", -] - -[[package]] -name = "snark-verifier-sdk" -version = "0.1.1" -dependencies = [ - "ark-std", - "bincode", - "bus-mapping", - "criterion", - "criterion-macro", - "crossterm", - "eth-types", - "ethereum-types 0.14.1", - "halo2-base", - "hex", - "itertools", - "lazy_static", - "mock", - "num-bigint", - "num-integer", - "num-traits", - "paste", - "pprof", - "rand", - "rand_chacha", - "serde", - "serde_json", - "serde_with 2.3.3", - "snark-verifier 0.1.1", - "tui", - "zkevm-circuits", -] - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - -[[package]] -name = "spki" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b" -dependencies = [ - "base64ct", - "der", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "str_stack" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb" - -[[package]] -name = "strsim" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" - -[[package]] -name = "strum" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" -dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 1.0.109", -] - -[[package]] -name = "substrate-bn" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" -dependencies = [ - "byteorder", - "crunchy", - "lazy_static", - "rand", - "rustc-hex", -] - -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - -[[package]] -name = "symbolic-common" -version = "10.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b55cdc318ede251d0957f07afe5fed912119b8c1bc5a7804151826db999e737" -dependencies = [ - "debugid", - "memmap2", - "stable_deref_trait", - "uuid 1.3.3", -] - -[[package]] -name = "symbolic-demangle" -version = "10.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79be897be8a483a81fff6a3a4e195b4ac838ef73ca42d348b3f722da9902e489" -dependencies = [ - "cpp_demangle", - "rustc-demangle", - "symbolic-common", -] - -[[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.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" -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 = "tempfile" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall 0.3.5", - "rustix", - "windows-sys 0.45.0", -] - -[[package]] -name = "termcolor" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" - -[[package]] -name = "thiserror" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", -] - -[[package]] -name = "time" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc" -dependencies = [ - "itoa", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" - -[[package]] -name = "time-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b" -dependencies = [ - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "tinyvec" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" -dependencies = [ - "tinyvec_macros", -] - -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - -[[package]] -name = "tokio" -version = "1.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105" -dependencies = [ - "autocfg", - "bytes", - "libc", - "mio", - "pin-project-lite", - "socket2", - "windows-sys 0.48.0", -] - -[[package]] -name = "tokio-rustls" -version = "0.23.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" -dependencies = [ - "rustls 0.20.8", - "tokio", - "webpki", -] - -[[package]] -name = "tokio-rustls" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5" -dependencies = [ - "rustls 0.21.1", - "tokio", -] - -[[package]] -name = "tokio-tungstenite" -version = "0.17.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181" -dependencies = [ - "futures-util", - "log", - "rustls 0.20.8", - "tokio", - "tokio-rustls 0.23.4", - "tungstenite", - "webpki", - "webpki-roots", -] - -[[package]] -name = "tokio-util" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "toml" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_datetime" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f" - -[[package]] -name = "toml_edit" -version = "0.19.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d964908cec0d030b812013af25a0e57fddfadb1e066ecc6681d86253129d4f" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "tracing-futures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" -dependencies = [ - "pin-project", - "tracing", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "tui" -version = "0.19.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccdd26cbd674007e649a272da4475fb666d3aa0ad0531da7136db6fab0e5bad1" -dependencies = [ - "bitflags", - "cassowary", - "crossterm", - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "tungstenite" -version = "0.17.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0" -dependencies = [ - "base64 0.13.1", - "byteorder", - "bytes", - "http", - "httparse", - "log", - "rand", - "rustls 0.20.8", - "sha-1", - "thiserror", - "url", - "utf-8", - "webpki", -] - -[[package]] -name = "typenum" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" - -[[package]] -name = "uint" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76f64bba2c53b04fcab63c01a7d7427eadc821e3bc48c34dc9ba29c501164b52" -dependencies = [ - "byteorder", - "crunchy", - "hex", - "static_assertions", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" - -[[package]] -name = "unicode-ident" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] - -[[package]] -name = "unicode-segmentation" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "unicode-xid" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" - -[[package]] -name = "untrusted" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" - -[[package]] -name = "url" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom", - "serde", -] - -[[package]] -name = "uuid" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "walkdir" -version = "2.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" -dependencies = [ - "same-file", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" -dependencies = [ - "log", - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 2.0.16", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.16", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93" - -[[package]] -name = "wasm-timer" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be0ecb0db480561e9a7642b5d3e4187c128914e58aa84330b9493e3eb68c5e7f" -dependencies = [ - "futures", - "js-sys", - "parking_lot 0.11.2", - "pin-utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "web-sys" -version = "0.3.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webpki" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" -dependencies = [ - "ring", - "untrusted", -] - -[[package]] -name = "webpki-roots" -version = "0.22.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" -dependencies = [ - "webpki", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "winnow" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" -dependencies = [ - "winapi", -] - -[[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", - "send_wrapper", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[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.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" - -[[package]] -name = "zkevm-circuits" -version = "0.1.0" -source = "git+https://github.com/privacy-scaling-explorations/zkevm-circuits.git?rev=f834e61#f834e61ed2937adfecbb5fdad9cab711871c27ac" -dependencies = [ - "array-init", - "bus-mapping", - "ecc", - "ecdsa 0.1.0", - "env_logger", - "eth-types", - "ethers-core", - "ethers-signers", - "gadgets", - "halo2_proofs 0.2.0 (git+https://github.com/privacy-scaling-explorations/halo2.git?tag=v2023_02_02)", - "integer", - "itertools", - "keccak256", - "lazy_static", - "libsecp256k1", - "log", - "maingate", - "mock", - "num", - "num-bigint", - "rand", - "rand_chacha", - "rand_xorshift", - "sha3 0.10.8", - "snark-verifier 0.1.0", - "strum", - "strum_macros", - "subtle", -] - -[[patch.unused]] -name = "poseidon" -version = "0.2.0" diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index 7069bf26..986f30eb 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -17,11 +17,11 @@ serde_json = "1.0" serde_with = { version = "2.2", optional = true } bincode = "1.3.3" ark-std = { version = "0.3.0", features = ["print-trace"], optional = true } -halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "release-0.3.0", default-features = false } +halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } snark-verifier = { path = "../snark-verifier", default-features = false } # loader_evm -ethereum-types = { version = "0.14", default-features = false, features = ["std"], optional = true } +ethereum-types = { version = "0.14.1", default-features = false, features = ["std"], optional = true } # sha3 = { version = "0.10", optional = true } # revm = { version = "2.3.1", optional = true } # bytes = { version = "1.2", optional = true } diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index 81248a2d..313fd038 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -16,17 +16,17 @@ serde = { version = "1.0", features = ["derive"] } # Use halo2-base as non-optional dependency because it re-exports halo2_proofs, halo2curves, and poseidon, using different repos based on feature flag "halo2-axiom" or "halo2-pse" halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } # This is Scroll's audited poseidon circuit. We only use it for the Native Poseidon spec. We do not use the halo2 circuit at all (and it wouldn't even work because the halo2_proofs tag is not compatbile). -poseidon-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit.git" } +poseidon-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit.git", rev = "50015b7" } # parallel rayon = { version = "1.7.0", optional = true } # loader_evm -sha3 = { version = "0.10", optional = true } -bytes = { version = "1.1.0", default-features = false, optional = true } +sha3 = { version = "0.10.8", optional = true } +bytes = { version = "1.4.0", default-features = false, optional = true } primitive-types = { version = "0.12.1", default-features = false, features = ["std"], optional = true } rlp = { version = "0.5.2", default-features = false, features = ["std"], optional = true } -revm = { version = "= 2.3.1", optional = true } +revm = { version = "2.3.1", optional = true } # loader_halo2 halo2-ecc = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false, optional = true } From 7a0fd966dd62e9f076c7631b5f541af5d44e1fac Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Thu, 20 Jul 2023 17:36:32 -0400 Subject: [PATCH 03/19] feat: remove use of env vars for circuit configuration (#22) * feat: remove use of env vars for circuit configuration This is a companion to https://github.com/axiom-crypto/halo2-lib/pull/92 * chore: remove rustfmt CI check PSE upstream uses different rustfmt configuration than us, so some files disagree in formatting --- .github/workflows/ci.yaml | 4 - snark-verifier-sdk/Cargo.toml | 2 +- snark-verifier-sdk/benches/standard_plonk.rs | 13 +- snark-verifier-sdk/src/halo2/aggregation.rs | 52 ++++--- snark-verifier/Cargo.toml | 4 +- .../examples/evm-verifier-with-accumulator.rs | 145 +++++------------- snark-verifier/examples/recursion.rs | 127 +++++---------- snark-verifier/src/loader/evm/code.rs | 4 +- 8 files changed, 111 insertions(+), 240 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 634eed77..e057f89d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -29,7 +29,6 @@ jobs: - name: Run test run: cargo test --all -- --nocapture - lint: name: Lint runs-on: ubuntu-latest @@ -47,8 +46,5 @@ jobs: with: cache-on-failure: true - - name: Run fmt - run: cargo fmt --all -- --check - - name: Run clippy run: cargo clippy --all --all-targets -- -D warnings diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index 986f30eb..896dbccf 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -17,7 +17,7 @@ serde_json = "1.0" serde_with = { version = "2.2", optional = true } bincode = "1.3.3" ark-std = { version = "0.3.0", features = ["print-trace"], optional = true } -halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } +halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "feat/test_suite", default-features = false } snark-verifier = { path = "../snark-verifier", default-features = false } # loader_evm diff --git a/snark-verifier-sdk/benches/standard_plonk.rs b/snark-verifier-sdk/benches/standard_plonk.rs index 70d600ea..f696f822 100644 --- a/snark-verifier-sdk/benches/standard_plonk.rs +++ b/snark-verifier-sdk/benches/standard_plonk.rs @@ -1,17 +1,16 @@ +use ark_std::{end_timer, start_timer}; use criterion::{criterion_group, criterion_main}; use criterion::{BenchmarkId, Criterion}; -use halo2_base::gates::builder::CircuitBuilderStage; -use halo2_base::utils::fs::gen_srs; -use pprof::criterion::{Output, PProfProfiler}; -use rand::rngs::OsRng; -use std::path::Path; -use ark_std::{end_timer, start_timer}; +use halo2_base::gates::builder::{CircuitBuilderStage, BASE_CONFIG_PARAMS}; use halo2_base::halo2_proofs; +use halo2_base::utils::fs::gen_srs; use halo2_proofs::halo2curves as halo2_curves; use halo2_proofs::{ halo2curves::bn256::Bn256, poly::{commitment::Params, kzg::commitment::ParamsKZG}, }; +use pprof::criterion::{Output, PProfProfiler}; +use rand::rngs::OsRng; use snark_verifier_sdk::evm::{evm_verify, gen_evm_proof_shplonk, gen_evm_verifier_shplonk}; use snark_verifier_sdk::halo2::aggregation::AggregationConfigParams; use snark_verifier_sdk::{ @@ -20,6 +19,7 @@ use snark_verifier_sdk::{ Snark, }; use snark_verifier_sdk::{CircuitExt, SHPLONK}; +use std::path::Path; mod application { use super::halo2_curves::bn256::Fr; @@ -185,6 +185,7 @@ fn bench(c: &mut Criterion) { let snarks = [(); 3].map(|_| gen_application_snark(¶ms_app)); let agg_config = AggregationConfigParams::from_path(path); + BASE_CONFIG_PARAMS.with(|params| *params.borrow_mut() = agg_config.into()); let params = gen_srs(agg_config.degree); let lookup_bits = params.k() as usize - 1; diff --git a/snark-verifier-sdk/src/halo2/aggregation.rs b/snark-verifier-sdk/src/halo2/aggregation.rs index b5dc148d..9f9ac64a 100644 --- a/snark-verifier-sdk/src/halo2/aggregation.rs +++ b/snark-verifier-sdk/src/halo2/aggregation.rs @@ -3,10 +3,11 @@ use crate::{BITS, LIMBS}; use halo2_base::{ gates::{ builder::{ - CircuitBuilderStage, FlexGateConfigParams, GateThreadBuilder, - MultiPhaseThreadBreakPoints, RangeCircuitBuilder, RangeWithInstanceCircuitBuilder, - RangeWithInstanceConfig, + BaseConfigParams, CircuitBuilderStage, GateThreadBuilder, MultiPhaseThreadBreakPoints, + PublicBaseConfig, RangeCircuitBuilder, RangeWithInstanceCircuitBuilder, + BASE_CONFIG_PARAMS, }, + flex_gate::GateStrategy, RangeChip, }, halo2_proofs::{ @@ -38,12 +39,7 @@ use snark_verifier::{ }, verifier::SnarkVerifier, }; -use std::{ - env::{set_var, var}, - fs::File, - path::Path, - rc::Rc, -}; +use std::{fs::File, path::Path, rc::Rc}; use super::{CircuitExt, PoseidonTranscript, Snark, POSEIDON_SPEC}; @@ -143,7 +139,7 @@ where /// Same as `FlexGateConfigParams` except we assume a single Phase and default 'Vertical' strategy. /// Also adds `lookup_bits` field. -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, Serialize, Deserialize)] pub struct AggregationConfigParams { pub degree: u32, pub num_advice: usize, @@ -159,6 +155,19 @@ impl AggregationConfigParams { } } +impl From for BaseConfigParams { + fn from(params: AggregationConfigParams) -> Self { + BaseConfigParams { + strategy: GateStrategy::Vertical, + k: params.degree as usize, + num_advice_per_phase: vec![params.num_advice], + num_lookup_advice_per_phase: vec![params.num_lookup_advice], + num_fixed: params.num_fixed, + lookup_bits: Some(params.lookup_bits), + } + } +} + #[derive(Clone, Debug)] pub struct AggregationCircuit { pub inner: RangeWithInstanceCircuitBuilder, @@ -314,11 +323,12 @@ impl AggregationCircuit { where AS: for<'a> Halo2KzgAccumulationScheme<'a>, { - let lookup_bits = params.k() as usize - 1; // almost always we just use the max lookup bits possible, which is k - 1 because of blinding factors + let lookup_bits = BASE_CONFIG_PARAMS + .with(|conf| conf.borrow().lookup_bits) + .unwrap_or(params.k() as usize - 1); let circuit = Self::new::(CircuitBuilderStage::Keygen, None, lookup_bits, params, snarks); circuit.config(params.k(), Some(10)); - set_var("LOOKUP_BITS", lookup_bits.to_string()); circuit } @@ -331,18 +341,16 @@ impl AggregationCircuit { where AS: for<'a> Halo2KzgAccumulationScheme<'a>, { - let lookup_bits: usize = var("LOOKUP_BITS").expect("LOOKUP_BITS not set").parse().unwrap(); - let circuit = Self::new::( + let lookup_bits = BASE_CONFIG_PARAMS + .with(|conf| conf.borrow().lookup_bits) + .unwrap_or(params.k() as usize - 1); + Self::new::( CircuitBuilderStage::Prover, Some(break_points), lookup_bits, params, snarks, - ); - let minimum_rows = var("MINIMUM_ROWS").map(|s| s.parse().unwrap_or(10)).unwrap_or(10); - circuit.config(params.k(), Some(minimum_rows)); - set_var("LOOKUP_BITS", lookup_bits.to_string()); - circuit + ) } /// Re-expose the previous public instances of aggregated snarks again. @@ -359,7 +367,7 @@ impl AggregationCircuit { &self.as_proof[..] } - pub fn config(&self, k: u32, minimum_rows: Option) -> FlexGateConfigParams { + pub fn config(&self, k: u32, minimum_rows: Option) -> BaseConfigParams { self.inner.config(k, minimum_rows) } @@ -386,12 +394,12 @@ impl CircuitExt for RangeWithInstanceCircuitBuilder { } fn selectors(config: &Self::Config) -> Vec { - config.range.gate.basic_gates[0].iter().map(|gate| gate.q_enable).collect() + config.base.gate().basic_gates[0].iter().map(|gate| gate.q_enable).collect() } } impl Circuit for AggregationCircuit { - type Config = RangeWithInstanceConfig; + type Config = PublicBaseConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index 313fd038..bf8b7fd5 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -14,7 +14,7 @@ rand = "0.8" serde = { version = "1.0", features = ["derive"] } # Use halo2-base as non-optional dependency because it re-exports halo2_proofs, halo2curves, and poseidon, using different repos based on feature flag "halo2-axiom" or "halo2-pse" -halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } +halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "feat/test_suite", default-features = false } # This is Scroll's audited poseidon circuit. We only use it for the Native Poseidon spec. We do not use the halo2 circuit at all (and it wouldn't even work because the halo2_proofs tag is not compatbile). poseidon-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit.git", rev = "50015b7" } @@ -29,7 +29,7 @@ rlp = { version = "0.5.2", default-features = false, features = ["std"], optiona revm = { version = "2.3.1", optional = true } # loader_halo2 -halo2-ecc = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false, optional = true } +halo2-ecc = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "feat/test_suite", default-features = false, optional = true } [dev-dependencies] ark-std = { version = "0.3.0", features = ["print-trace"] } diff --git a/snark-verifier/examples/evm-verifier-with-accumulator.rs b/snark-verifier/examples/evm-verifier-with-accumulator.rs index dd537880..4ffa6459 100644 --- a/snark-verifier/examples/evm-verifier-with-accumulator.rs +++ b/snark-verifier/examples/evm-verifier-with-accumulator.rs @@ -1,5 +1,9 @@ use aggregation::{AggregationCircuit, AggregationConfigParams}; -use halo2_base::{gates::builder::CircuitBuilderStage, halo2_proofs, utils::fs::gen_srs}; +use halo2_base::{ + gates::builder::{set_lookup_bits, CircuitBuilderStage}, + halo2_proofs, + utils::fs::gen_srs, +}; use halo2_proofs::{ dev::MockProver, halo2curves::bn256::{Bn256, Fq, Fr, G1Affine}, @@ -26,7 +30,7 @@ use snark_verifier::{ system::halo2::{compile, transcript::evm::EvmTranscript, Config}, verifier::{self, SnarkVerifier}, }; -use std::{env::set_var, fs::File, io::Cursor, rc::Rc}; +use std::{fs::File, io::Cursor, rc::Rc}; const LIMBS: usize = 3; const BITS: usize = 88; @@ -200,20 +204,16 @@ mod aggregation { use super::halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, - plonk::{self, Circuit, Column, Instance}, + plonk::{self, Circuit}, }; use super::{As, BITS, LIMBS}; use super::{Fr, G1Affine}; - use halo2_base::{ - gates::{ - builder::{ - assign_threads_in, CircuitBuilderStage, FlexGateConfigParams, GateThreadBuilder, - MultiPhaseThreadBreakPoints, RangeCircuitBuilder, - }, - range::RangeConfig, - RangeChip, + use halo2_base::gates::{ + builder::{ + BaseConfigParams, CircuitBuilderStage, GateThreadBuilder, MultiPhaseThreadBreakPoints, + PublicBaseConfig, RangeWithInstanceCircuitBuilder, }, - AssignedValue, SKIP_FIRST_PASS, + RangeChip, }; use halo2_ecc::bn254::FpChip; use itertools::Itertools; @@ -228,7 +228,7 @@ mod aggregation { util::arithmetic::fe_to_limbs, verifier::{plonk::PlonkProtocol, SnarkVerifier}, }; - use std::{collections::HashMap, rc::Rc}; + use std::rc::Rc; const T: usize = 3; const RATE: usize = 2; @@ -309,17 +309,10 @@ mod aggregation { pub lookup_bits: usize, } - #[derive(Clone)] - pub struct AggregationConfig { - pub range: RangeConfig, - pub instance: Column, - } - #[derive(Clone, Debug)] pub struct AggregationCircuit { - pub circuit: RangeCircuitBuilder, + pub inner: RangeWithInstanceCircuitBuilder, pub as_proof: Vec, - pub assigned_instances: Vec>, } impl AggregationCircuit { @@ -398,22 +391,28 @@ mod aggregation { } let builder = loader.take_ctx(); - let circuit = match stage { - CircuitBuilderStage::Mock => RangeCircuitBuilder::mock(builder), - CircuitBuilderStage::Keygen => RangeCircuitBuilder::keygen(builder), - CircuitBuilderStage::Prover => { - RangeCircuitBuilder::prover(builder, break_points.unwrap()) + let inner = match stage { + CircuitBuilderStage::Mock => { + RangeWithInstanceCircuitBuilder::mock(builder, assigned_instances) + } + CircuitBuilderStage::Keygen => { + RangeWithInstanceCircuitBuilder::keygen(builder, assigned_instances) } + CircuitBuilderStage::Prover => RangeWithInstanceCircuitBuilder::prover( + builder, + assigned_instances, + break_points.unwrap(), + ), }; - Self { circuit, as_proof, assigned_instances } + Self { inner, as_proof } } - pub fn config(&self, k: u32, minimum_rows: Option) -> FlexGateConfigParams { - self.circuit.0.builder.borrow().config(k as usize, minimum_rows) + pub fn config(&self, k: u32, minimum_rows: Option) -> BaseConfigParams { + self.inner.circuit.0.builder.borrow().config(k as usize, minimum_rows) } pub fn break_points(&self) -> MultiPhaseThreadBreakPoints { - self.circuit.0.break_points.borrow().clone() + self.inner.circuit.0.break_points.borrow().clone() } pub fn num_instance() -> Vec { @@ -422,7 +421,7 @@ mod aggregation { } pub fn instances(&self) -> Vec> { - vec![self.assigned_instances.iter().map(|v| *v.value()).collect_vec()] + vec![self.inner.assigned_instances.iter().map(|v| *v.value()).collect_vec()] } pub fn accumulator_indices() -> Vec<(usize, usize)> { @@ -431,7 +430,7 @@ mod aggregation { } impl Circuit for AggregationCircuit { - type Config = AggregationConfig; + type Config = PublicBaseConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -439,89 +438,15 @@ mod aggregation { } fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { - let range = RangeCircuitBuilder::configure(meta); - let instance = meta.instance_column(); - meta.enable_equality(instance); - AggregationConfig { range, instance } + RangeWithInstanceCircuitBuilder::configure(meta) } fn synthesize( &self, config: Self::Config, - mut layouter: impl Layouter, + layouter: impl Layouter, ) -> Result<(), plonk::Error> { - // copied from RangeCircuitBuilder::synthesize but with extra logic to expose public instances - let range = config.range; - let circuit = &self.circuit.0; - range.load_lookup_table(&mut layouter).expect("load lookup table should not fail"); - - // we later `take` the builder, so we need to save this value - let witness_gen_only = circuit.builder.borrow().witness_gen_only(); - let mut assigned_advices = HashMap::new(); - - let mut first_pass = SKIP_FIRST_PASS; - layouter - .assign_region( - || "AggregationCircuit", - |mut region| { - if first_pass { - first_pass = false; - return Ok(()); - } - // only support FirstPhase in this Builder because getting challenge value requires more specialized witness generation during synthesize - if !witness_gen_only { - // clone the builder so we can re-use the circuit for both vk and pk gen - let builder = circuit.builder.borrow(); - let assignments = builder.assign_all( - &range.gate, - &range.lookup_advice, - &range.q_lookup, - &mut region, - Default::default(), - ); - *circuit.break_points.borrow_mut() = assignments.break_points; - assigned_advices = assignments.assigned_advices; - } else { - #[cfg(feature = "display")] - let start0 = std::time::Instant::now(); - let builder = circuit.builder.take(); - let break_points = circuit.break_points.take(); - for (phase, (threads, break_points)) in builder - .threads - .into_iter() - .zip(break_points.into_iter()) - .enumerate() - .take(1) - { - assign_threads_in( - phase, - threads, - &range.gate, - &range.lookup_advice[phase], - &mut region, - break_points, - ); - } - #[cfg(feature = "display")] - println!("assign threads in {:?}", start0.elapsed()); - } - Ok(()) - }, - ) - .unwrap(); - - if !witness_gen_only { - // expose public instances - let mut layouter = layouter.namespace(|| "expose"); - for (i, instance) in self.assigned_instances.iter().enumerate() { - let cell = instance.cell.unwrap(); - let (cell, _) = assigned_advices - .get(&(cell.context_id, cell.offset)) - .expect("instance not assigned"); - layouter.constrain_instance(*cell, config.instance, i); - } - } - Ok(()) + self.inner.synthesize(config, layouter) } } } @@ -649,6 +574,7 @@ fn main() { File::open(path).unwrap_or_else(|e| panic!("{path} does not exist: {e:?}")), ) .unwrap(); + set_lookup_bits(agg_config.lookup_bits); let agg_circuit = AggregationCircuit::new( CircuitBuilderStage::Mock, None, @@ -657,7 +583,6 @@ fn main() { snarks.clone(), ); agg_circuit.config(agg_config.degree, Some(6)); - set_var("LOOKUP_BITS", agg_config.lookup_bits.to_string()); #[cfg(debug_assertions)] { MockProver::run(agg_config.degree, &agg_circuit, agg_circuit.instances()) diff --git a/snark-verifier/examples/recursion.rs b/snark-verifier/examples/recursion.rs index 5829e1b7..7415e1ab 100644 --- a/snark-verifier/examples/recursion.rs +++ b/snark-verifier/examples/recursion.rs @@ -2,9 +2,10 @@ use ark_std::{end_timer, start_timer}; use common::*; -use halo2_base::gates::flex_gate::GateStrategy; +use halo2_base::gates::builder::BaseConfigParams; +use halo2_base::gates::{builder::BASE_CONFIG_PARAMS, flex_gate::GateStrategy}; +use halo2_base::halo2_proofs; use halo2_base::utils::fs::gen_srs; -use halo2_base::{gates::builder::FlexGateConfigParams, halo2_proofs}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, dev::MockProver, @@ -46,7 +47,7 @@ use snark_verifier::{ SnarkVerifier, }, }; -use std::{env::set_var, fs, iter, marker::PhantomData, rc::Rc}; +use std::{fs, iter, marker::PhantomData, rc::Rc}; use crate::recursion::AggregationConfigParams; @@ -323,18 +324,17 @@ mod application { } mod recursion { - use std::{collections::HashMap, env::var}; - use halo2_base::{ gates::{ - builder::{GateThreadBuilder, RangeCircuitBuilder}, - range::RangeConfig, + builder::{ + GateThreadBuilder, PublicBaseConfig, RangeWithInstanceCircuitBuilder, + BASE_CONFIG_PARAMS, + }, GateInstructions, RangeChip, RangeInstructions, }, AssignedValue, }; use halo2_ecc::{bn254::FpChip, ecc::EcPoint}; - use halo2_proofs::plonk::{Column, Instance}; use snark_verifier::loader::halo2::{EccInstructions, IntegerInstructions}; use super::*; @@ -412,8 +412,8 @@ mod recursion { .map(|(lhs, rhs)| { loader.ecc_chip().select( loader.ctx_mut().main(0), - EcPoint::clone(&lhs), - EcPoint::clone(&rhs), + EcPoint::clone(lhs), + EcPoint::clone(rhs), *condition, ) }) @@ -446,24 +446,18 @@ mod recursion { pub lookup_bits: usize, } - #[derive(Clone)] - pub struct RecursionConfig { - pub range: RangeConfig, - pub instance: Column, - } - #[derive(Clone)] pub struct RecursionCircuit { svk: Svk, default_accumulator: KzgAccumulator, app: Snark, previous: Snark, + #[allow(dead_code)] round: usize, instances: Vec, as_proof: Vec, - inner: RangeCircuitBuilder, - assigned_instances: Vec>, + inner: RangeWithInstanceCircuitBuilder, } impl RecursionCircuit { @@ -534,24 +528,16 @@ mod recursion { .collect(); let builder = GateThreadBuilder::mock(); - let inner = RangeCircuitBuilder::mock(builder); - let mut circuit = Self { - svk, - default_accumulator, - app: app, - previous: previous, - round, - instances, - as_proof, - inner, - assigned_instances: vec![], - }; + let inner = RangeWithInstanceCircuitBuilder::mock(builder, vec![]); + let mut circuit = + Self { svk, default_accumulator, app, previous, round, instances, as_proof, inner }; circuit.build(); circuit } fn build(&mut self) { - let lookup_bits = var("LOOKUP_BITS").unwrap().parse().unwrap(); + let lookup_bits = + BASE_CONFIG_PARAMS.with(|params| params.borrow().lookup_bits.unwrap()); let range = RangeChip::::default(lookup_bits); let main_gate = range.gate(); let mut builder = GateThreadBuilder::mock(); @@ -629,9 +615,9 @@ mod recursion { ] { ctx.constrain_equal(lhs, rhs); } - *self.inner.0.builder.borrow_mut() = builder; + *self.inner.circuit.0.builder.borrow_mut() = builder; - self.assigned_instances.extend( + self.inner.assigned_instances.extend( [lhs.x(), lhs.y(), rhs.x(), rhs.y()] .into_iter() .flat_map(|coordinate| coordinate.limbs()) @@ -670,7 +656,7 @@ mod recursion { } impl Circuit for RecursionCircuit { - type Config = RecursionConfig; + type Config = PublicBaseConfig; type FloorPlanner = SimpleFloorPlanner; fn without_witnesses(&self) -> Self { @@ -678,59 +664,15 @@ mod recursion { } fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { - let range = RangeCircuitBuilder::configure(meta); - let instance = meta.instance_column(); - meta.enable_equality(instance); - RecursionConfig { range, instance } + RangeWithInstanceCircuitBuilder::configure(meta) } fn synthesize( &self, config: Self::Config, - mut layouter: impl Layouter, + layouter: impl Layouter, ) -> Result<(), Error> { - let range = config.range; - range.load_lookup_table(&mut layouter).expect("load lookup table should not fail"); - let circuit = &self.inner.0; - - let mut assigned_advices = HashMap::new(); - // POC so will only do mock prover and not real prover - let mut first_pass = halo2_base::SKIP_FIRST_PASS; // assume using simple floor planner - layouter - .assign_region( - || "Recursion Circuit", - |mut region| { - if first_pass { - first_pass = false; - return Ok(()); - } - // clone the builder so we can re-use the circuit for both vk and pk gen - let builder = circuit.builder.borrow(); - let assignments = builder.assign_all( - &range.gate, - &range.lookup_advice, - &range.q_lookup, - &mut region, - Default::default(), - ); - *circuit.break_points.borrow_mut() = assignments.break_points; - assigned_advices = assignments.assigned_advices; - Ok(()) - }, - ) - .unwrap(); - - // expose public instances - let mut layouter = layouter.namespace(|| "expose"); - for (i, instance) in self.assigned_instances.iter().enumerate() { - let cell = instance.cell.unwrap(); - let (cell, _) = assigned_advices - .get(&(cell.context_id, cell.offset)) - .expect("instance not assigned"); - layouter.constrain_instance(*cell, config.instance, i); - } - - Ok(()) + self.inner.synthesize(config, layouter) } } @@ -749,7 +691,7 @@ mod recursion { } fn selectors(config: &Self::Config) -> Vec { - config.range.gate.basic_gates[0].iter().map(|gate| gate.q_enable).collect() + config.base.gate().basic_gates[0].iter().map(|gate| gate.q_enable).collect() } } @@ -805,20 +747,21 @@ mod recursion { } fn main() { - let app_params = gen_srs(3); + let app_params = gen_srs(5); let recursion_config: AggregationConfigParams = serde_json::from_reader(fs::File::open("configs/example_recursion.json").unwrap()).unwrap(); let k = recursion_config.degree; let recursion_params = gen_srs(k); - let flex_gate_config = FlexGateConfigParams { - strategy: GateStrategy::Vertical, - k: k as usize, - num_advice_per_phase: vec![recursion_config.num_advice], - num_lookup_advice_per_phase: vec![recursion_config.num_lookup_advice], - num_fixed: recursion_config.num_fixed, - }; - set_var("FLEX_GATE_CONFIG_PARAMS", serde_json::to_string(&flex_gate_config).unwrap()); - set_var("LOOKUP_BITS", recursion_config.lookup_bits.to_string()); + BASE_CONFIG_PARAMS.with(|params| { + *params.borrow_mut() = BaseConfigParams { + strategy: GateStrategy::Vertical, + k: k as usize, + num_advice_per_phase: vec![recursion_config.num_advice], + num_lookup_advice_per_phase: vec![recursion_config.num_lookup_advice], + num_fixed: recursion_config.num_fixed, + lookup_bits: Some(recursion_config.lookup_bits), + } + }); let app_pk = gen_pk(&app_params, &application::Square::default()); diff --git a/snark-verifier/src/loader/evm/code.rs b/snark-verifier/src/loader/evm/code.rs index 2fec71d2..236684d6 100644 --- a/snark-verifier/src/loader/evm/code.rs +++ b/snark-verifier/src/loader/evm/code.rs @@ -13,9 +13,7 @@ pub struct YulCode { impl YulCode { pub fn new() -> Self { - YulCode { - runtime: String::new(), - } + YulCode { runtime: String::new() } } pub fn code(&self, base_modulus: String, scalar_modulus: String) -> String { From cbf7219cbac17dc0c2d661be26484897935da425 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Thu, 20 Jul 2023 21:47:01 -0400 Subject: [PATCH 04/19] chore: fix dependencies --- snark-verifier-sdk/Cargo.toml | 2 +- snark-verifier/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index 896dbccf..986f30eb 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -17,7 +17,7 @@ serde_json = "1.0" serde_with = { version = "2.2", optional = true } bincode = "1.3.3" ark-std = { version = "0.3.0", features = ["print-trace"], optional = true } -halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "feat/test_suite", default-features = false } +halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } snark-verifier = { path = "../snark-verifier", default-features = false } # loader_evm diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index bf8b7fd5..313fd038 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -14,7 +14,7 @@ rand = "0.8" serde = { version = "1.0", features = ["derive"] } # Use halo2-base as non-optional dependency because it re-exports halo2_proofs, halo2curves, and poseidon, using different repos based on feature flag "halo2-axiom" or "halo2-pse" -halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "feat/test_suite", default-features = false } +halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } # This is Scroll's audited poseidon circuit. We only use it for the Native Poseidon spec. We do not use the halo2 circuit at all (and it wouldn't even work because the halo2_proofs tag is not compatbile). poseidon-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit.git", rev = "50015b7" } @@ -29,7 +29,7 @@ rlp = { version = "0.5.2", default-features = false, features = ["std"], optiona revm = { version = "2.3.1", optional = true } # loader_halo2 -halo2-ecc = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "feat/test_suite", default-features = false, optional = true } +halo2-ecc = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false, optional = true } [dev-dependencies] ark-std = { version = "0.3.0", features = ["print-trace"] } From 4aba23a69feb7bd0b8ded5d5aca112d07876519a Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Thu, 27 Jul 2023 09:55:22 -0700 Subject: [PATCH 05/19] Feat/read pk buffer capacity (#24) * feat: change default `read_pk` buffer capacity to 1MB * feat: add bench for read_pk --- snark-verifier-sdk/Cargo.toml | 5 + snark-verifier-sdk/benches/read_pk.rs | 216 ++++++++++++++++++++++++++ snark-verifier-sdk/src/lib.rs | 17 +- 3 files changed, 234 insertions(+), 4 deletions(-) create mode 100644 snark-verifier-sdk/benches/read_pk.rs diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index 986f30eb..e85f614f 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -69,3 +69,8 @@ harness = false name = "zkevm_plus_state" required-features = ["loader_halo2", "loader_evm", "zkevm", "halo2-pse"] harness = false + +[[bench]] +name = "read_pk" +required-features = ["loader_halo2"] +harness = false \ No newline at end of file diff --git a/snark-verifier-sdk/benches/read_pk.rs b/snark-verifier-sdk/benches/read_pk.rs new file mode 100644 index 00000000..02d25ec6 --- /dev/null +++ b/snark-verifier-sdk/benches/read_pk.rs @@ -0,0 +1,216 @@ +use ark_std::{end_timer, start_timer}; +use criterion::Criterion; +use criterion::{criterion_group, criterion_main}; +use halo2_base::gates::builder::BASE_CONFIG_PARAMS; +use halo2_base::halo2_proofs; +use halo2_base::utils::fs::gen_srs; +use halo2_proofs::halo2curves as halo2_curves; +use halo2_proofs::{halo2curves::bn256::Bn256, poly::kzg::commitment::ParamsKZG}; +use pprof::criterion::{Output, PProfProfiler}; +use rand::rngs::OsRng; + +use snark_verifier_sdk::halo2::aggregation::AggregationConfigParams; +use snark_verifier_sdk::{ + gen_pk, + halo2::{aggregation::AggregationCircuit, gen_snark_shplonk}, + Snark, +}; +use snark_verifier_sdk::{read_pk_with_capacity, SHPLONK}; +use std::path::Path; + +mod application { + use super::halo2_curves::bn256::Fr; + use super::halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance}, + poly::Rotation, + }; + use rand::RngCore; + use snark_verifier_sdk::CircuitExt; + + #[derive(Clone, Copy)] + pub struct StandardPlonkConfig { + a: Column, + b: Column, + c: Column, + q_a: Column, + q_b: Column, + q_c: Column, + q_ab: Column, + constant: Column, + #[allow(dead_code)] + instance: Column, + } + + impl StandardPlonkConfig { + fn configure(meta: &mut ConstraintSystem) -> Self { + let [a, b, c] = [(); 3].map(|_| meta.advice_column()); + let [q_a, q_b, q_c, q_ab, constant] = [(); 5].map(|_| meta.fixed_column()); + let instance = meta.instance_column(); + + [a, b, c].map(|column| meta.enable_equality(column)); + + meta.create_gate( + "q_a·a + q_b·b + q_c·c + q_ab·a·b + constant + instance = 0", + |meta| { + let [a, b, c] = + [a, b, c].map(|column| meta.query_advice(column, Rotation::cur())); + let [q_a, q_b, q_c, q_ab, constant] = [q_a, q_b, q_c, q_ab, constant] + .map(|column| meta.query_fixed(column, Rotation::cur())); + let instance = meta.query_instance(instance, Rotation::cur()); + Some( + q_a * a.clone() + + q_b * b.clone() + + q_c * c + + q_ab * a * b + + constant + + instance, + ) + }, + ); + + StandardPlonkConfig { a, b, c, q_a, q_b, q_c, q_ab, constant, instance } + } + } + + #[derive(Clone, Default)] + pub struct StandardPlonk(Fr); + + impl StandardPlonk { + pub fn rand(mut rng: R) -> Self { + Self(Fr::from(rng.next_u32() as u64)) + } + } + + impl CircuitExt for StandardPlonk { + fn num_instance(&self) -> Vec { + vec![1] + } + + fn instances(&self) -> Vec> { + vec![vec![self.0]] + } + } + + impl Circuit for StandardPlonk { + type Config = StandardPlonkConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + meta.set_minimum_degree(4); + StandardPlonkConfig::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + layouter.assign_region( + || "", + |mut region| { + #[cfg(feature = "halo2-pse")] + { + region.assign_advice(|| "", config.a, 0, || Value::known(self.0))?; + region.assign_fixed(|| "", config.q_a, 0, || Value::known(-Fr::one()))?; + region.assign_advice( + || "", + config.a, + 1, + || Value::known(-Fr::from(5u64)), + )?; + for (idx, column) in (1..).zip([ + config.q_a, + config.q_b, + config.q_c, + config.q_ab, + config.constant, + ]) { + region.assign_fixed( + || "", + column, + 1, + || Value::known(Fr::from(idx as u64)), + )?; + } + let a = + region.assign_advice(|| "", config.a, 2, || Value::known(Fr::one()))?; + a.copy_advice(|| "", &mut region, config.b, 3)?; + a.copy_advice(|| "", &mut region, config.c, 4)?; + } + #[cfg(feature = "halo2-axiom")] + { + region.assign_advice(config.a, 0, Value::known(self.0)); + region.assign_fixed(config.q_a, 0, -Fr::one()); + region.assign_advice(config.a, 1, Value::known(-Fr::from(5u64))); + for (idx, column) in (1..).zip([ + config.q_a, + config.q_b, + config.q_c, + config.q_ab, + config.constant, + ]) { + region.assign_fixed(column, 1, Fr::from(idx as u64)); + } + + let a = region.assign_advice(config.a, 2, Value::known(Fr::one())); + a.copy_advice(&mut region, config.b, 3); + a.copy_advice(&mut region, config.c, 4); + } + + Ok(()) + }, + ) + } + } +} + +fn gen_application_snark(params: &ParamsKZG) -> Snark { + let circuit = application::StandardPlonk::rand(OsRng); + + let pk = gen_pk(params, &circuit, Some(Path::new("examples/app.pk"))); + gen_snark_shplonk(params, &pk, circuit, Some(Path::new("examples/app.snark"))) +} + +fn bench(c: &mut Criterion) { + let path = "./configs/example_evm_accumulator.json"; + let params_app = gen_srs(8); + + let snarks = [(); 3].map(|_| gen_application_snark(¶ms_app)); + let agg_config = AggregationConfigParams::from_path(path); + BASE_CONFIG_PARAMS.with(|params| *params.borrow_mut() = agg_config.into()); + let params = gen_srs(agg_config.degree); + + let agg_circuit = AggregationCircuit::keygen::(¶ms, snarks); + + let start0 = start_timer!(|| "gen vk & pk"); + gen_pk(¶ms, &agg_circuit, Some(Path::new("examples/agg.pk"))); + end_timer!(start0); + + let mut group = c.benchmark_group("read-pk"); + group.sample_size(10); + group.bench_with_input("1mb", &(1024 * 1024), |b, &c| { + b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk")) + }); + group.bench_with_input("10mb", &(10 * 1024 * 1024), |b, &c| { + b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk")) + }); + group.bench_with_input("100mb", &(100 * 1024 * 1024), |b, &c| { + b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk")) + }); + group.bench_with_input("1gb", &(1024 * 1024 * 1024), |b, &c| { + b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk")) + }); + group.finish(); +} + +criterion_group! { + name = benches; + config = Criterion::default().with_profiler(PProfProfiler::new(10, Output::Flamegraph(None))); + targets = bench +} +criterion_main!(benches); diff --git a/snark-verifier-sdk/src/lib.rs b/snark-verifier-sdk/src/lib.rs index 9a5833d6..07a15bc7 100644 --- a/snark-verifier-sdk/src/lib.rs +++ b/snark-verifier-sdk/src/lib.rs @@ -33,6 +33,8 @@ pub mod halo2; pub const LIMBS: usize = 3; pub const BITS: usize = 88; +const BUFFER_SIZE: usize = 1024 * 1024; // 1MB + /// AS stands for accumulation scheme. /// AS can be either `Kzg` (the original PLONK KZG multi-open) or `Kzg` (SHPLONK) pub type PlonkVerifier = verifier::plonk::PlonkVerifier>; @@ -77,12 +79,19 @@ pub trait CircuitExt: Circuit { } pub fn read_pk>(path: &Path) -> io::Result> { - let f = File::open(path)?; + read_pk_with_capacity::(BUFFER_SIZE, path) +} + +pub fn read_pk_with_capacity>( + capacity: usize, + path: impl AsRef, +) -> io::Result> { + let f = File::open(path.as_ref())?; #[cfg(feature = "display")] - let read_time = start_timer!(|| format!("Reading pkey from {path:?}")); + let read_time = start_timer!(|| format!("Reading pkey from {:?}", path.as_ref())); // BufReader is indeed MUCH faster than Read - let mut bufreader = BufReader::new(f); + let mut bufreader = BufReader::with_capacity(capacity, f); // But it's even faster to load the whole file into memory first and then process, // HOWEVER this requires twice as much memory to initialize // let initial_buffer_size = f.metadata().map(|m| m.len() as usize + 1).unwrap_or(0); @@ -121,7 +130,7 @@ pub fn gen_pk>( let write_time = start_timer!(|| format!("Writing pkey to {path:?}")); path.parent().and_then(|dir| fs::create_dir_all(dir).ok()).unwrap(); - let mut f = BufWriter::new(File::create(path).unwrap()); + let mut f = BufWriter::with_capacity(BUFFER_SIZE, File::create(path).unwrap()); pk.write(&mut f, SerdeFormat::RawBytesUnchecked).unwrap(); #[cfg(feature = "display")] From 4eded17c17eec17626e32af00e4524127c4c79be Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Tue, 15 Aug 2023 15:57:26 -0600 Subject: [PATCH 06/19] [Update] use ff v0.13 (#28) * feat(snark-verifier): update to ff v0.13 * feat(snark-verifier): update examples * feat(snark-verifier-sdk): update to ff v0.13 * fix: conversion from BaseConfigParams to AggregationConfigParams * chore: pin poseidon rev * refactor(sdk): add `AggregationCtxBuilder` for aggregation Contains the populated builder after aggregating, without creating the `AggregationCircuit`. Doesn't need config parameters and break points. * chore: update cargo --- Cargo.toml | 1 + rust-toolchain | 2 +- snark-verifier-sdk/Cargo.toml | 4 +- snark-verifier-sdk/benches/read_pk.rs | 29 +-- snark-verifier-sdk/benches/standard_plonk.rs | 16 +- snark-verifier-sdk/src/halo2/aggregation.rs | 172 ++++++++++-------- snark-verifier-sdk/src/lib.rs | 10 +- snark-verifier/Cargo.toml | 15 +- .../examples/evm-verifier-with-accumulator.rs | 79 ++++---- snark-verifier/examples/recursion.rs | 139 +++++++++----- snark-verifier/src/loader.rs | 24 +-- snark-verifier/src/loader/evm/loader.rs | 12 +- snark-verifier/src/loader/evm/test/tui.rs | 97 +++------- snark-verifier/src/loader/evm/util.rs | 2 +- .../src/loader/evm/util/executor.rs | 98 ++-------- snark-verifier/src/loader/halo2/loader.rs | 18 +- snark-verifier/src/loader/halo2/shim.rs | 35 ++-- snark-verifier/src/pcs/ipa.rs | 2 +- snark-verifier/src/pcs/ipa/accumulation.rs | 4 +- snark-verifier/src/pcs/ipa/decider.rs | 2 +- snark-verifier/src/pcs/ipa/multiopen/bgh19.rs | 12 +- snark-verifier/src/pcs/kzg.rs | 2 +- snark-verifier/src/pcs/kzg/accumulation.rs | 4 +- snark-verifier/src/pcs/kzg/accumulator.rs | 9 +- snark-verifier/src/pcs/kzg/decider.rs | 19 +- .../src/pcs/kzg/multiopen/bdfg21.rs | 152 ++++++---------- snark-verifier/src/pcs/kzg/multiopen/gwc19.rs | 25 +-- snark-verifier/src/system/halo2.rs | 14 +- snark-verifier/src/system/halo2/transcript.rs | 23 ++- .../src/system/halo2/transcript/halo2.rs | 20 +- snark-verifier/src/util/arithmetic.rs | 27 +-- snark-verifier/src/util/hash/poseidon.rs | 82 +++++---- .../src/util/hash/poseidon/tests.rs | 4 +- snark-verifier/src/util/msm.rs | 2 +- snark-verifier/src/util/poly.rs | 12 +- snark-verifier/src/verifier/plonk/proof.rs | 2 +- snark-verifier/src/verifier/plonk/protocol.rs | 4 +- 37 files changed, 587 insertions(+), 587 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 552212b3..53c98f1a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,7 @@ members = [ "snark-verifier", "snark-verifier-sdk", ] +resolver = "2" [profile.dev] opt-level = 3 diff --git a/rust-toolchain b/rust-toolchain index 51ab4759..ee2d639b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2022-10-28 \ No newline at end of file +nightly-2023-08-12 \ No newline at end of file diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index e85f614f..adf30bec 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snark-verifier-sdk" -version = "0.1.1" +version = "0.1.2" edition = "2021" [dependencies] @@ -53,7 +53,7 @@ parallel = ["snark-verifier/parallel"] halo2-pse = ["snark-verifier/halo2-pse", "dep:serde_with"] halo2-axiom = ["snark-verifier/halo2-axiom"] -zkevm = ["dep:zkevm-circuits", "dep:bus-mapping", "dep:mock", "dep:eth-types"] +# zkevm = ["dep:zkevm-circuits", "dep:bus-mapping", "dep:mock", "dep:eth-types"] [[bench]] name = "standard_plonk" diff --git a/snark-verifier-sdk/benches/read_pk.rs b/snark-verifier-sdk/benches/read_pk.rs index 02d25ec6..55154a2e 100644 --- a/snark-verifier-sdk/benches/read_pk.rs +++ b/snark-verifier-sdk/benches/read_pk.rs @@ -1,7 +1,7 @@ use ark_std::{end_timer, start_timer}; use criterion::Criterion; use criterion::{criterion_group, criterion_main}; -use halo2_base::gates::builder::BASE_CONFIG_PARAMS; +use halo2_base::gates::builder::CircuitBuilderStage; use halo2_base::halo2_proofs; use halo2_base::utils::fs::gen_srs; use halo2_proofs::halo2curves as halo2_curves; @@ -182,30 +182,37 @@ fn bench(c: &mut Criterion) { let snarks = [(); 3].map(|_| gen_application_snark(¶ms_app)); let agg_config = AggregationConfigParams::from_path(path); - BASE_CONFIG_PARAMS.with(|params| *params.borrow_mut() = agg_config.into()); let params = gen_srs(agg_config.degree); - let agg_circuit = AggregationCircuit::keygen::(¶ms, snarks); + let agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Keygen, + agg_config, + None, + ¶ms, + snarks, + ); + std::fs::remove_file("examples/agg.pk").ok(); let start0 = start_timer!(|| "gen vk & pk"); gen_pk(¶ms, &agg_circuit, Some(Path::new("examples/agg.pk"))); end_timer!(start0); let mut group = c.benchmark_group("read-pk"); group.sample_size(10); - group.bench_with_input("1mb", &(1024 * 1024), |b, &c| { - b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk")) + group.bench_with_input("buffer 1mb capacity", &(1024 * 1024), |b, &c| { + b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk", agg_config)) }); - group.bench_with_input("10mb", &(10 * 1024 * 1024), |b, &c| { - b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk")) + group.bench_with_input("buffer 10mb capacity", &(10 * 1024 * 1024), |b, &c| { + b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk", agg_config)) }); - group.bench_with_input("100mb", &(100 * 1024 * 1024), |b, &c| { - b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk")) + group.bench_with_input("buffer 100mb capacity", &(100 * 1024 * 1024), |b, &c| { + b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk", agg_config)) }); - group.bench_with_input("1gb", &(1024 * 1024 * 1024), |b, &c| { - b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk")) + group.bench_with_input("buffer 1gb capacity", &(1024 * 1024 * 1024), |b, &c| { + b.iter(|| read_pk_with_capacity::(c, "examples/agg.pk", agg_config)) }); group.finish(); + std::fs::remove_file("examples/agg.pk").unwrap(); } criterion_group! { diff --git a/snark-verifier-sdk/benches/standard_plonk.rs b/snark-verifier-sdk/benches/standard_plonk.rs index f696f822..eecb7140 100644 --- a/snark-verifier-sdk/benches/standard_plonk.rs +++ b/snark-verifier-sdk/benches/standard_plonk.rs @@ -1,7 +1,7 @@ use ark_std::{end_timer, start_timer}; use criterion::{criterion_group, criterion_main}; use criterion::{BenchmarkId, Criterion}; -use halo2_base::gates::builder::{CircuitBuilderStage, BASE_CONFIG_PARAMS}; +use halo2_base::gates::builder::CircuitBuilderStage; use halo2_base::halo2_proofs; use halo2_base::utils::fs::gen_srs; use halo2_proofs::halo2curves as halo2_curves; @@ -185,11 +185,15 @@ fn bench(c: &mut Criterion) { let snarks = [(); 3].map(|_| gen_application_snark(¶ms_app)); let agg_config = AggregationConfigParams::from_path(path); - BASE_CONFIG_PARAMS.with(|params| *params.borrow_mut() = agg_config.into()); let params = gen_srs(agg_config.degree); - let lookup_bits = params.k() as usize - 1; - let agg_circuit = AggregationCircuit::keygen::(¶ms, snarks.clone()); + let agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Keygen, + agg_config, + None, + ¶ms, + snarks.clone(), + ); let start0 = start_timer!(|| "gen vk & pk"); let pk = gen_pk(¶ms, &agg_circuit, Some(Path::new("agg.pk"))); @@ -205,8 +209,8 @@ fn bench(c: &mut Criterion) { b.iter(|| { let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Prover, + agg_config, Some(break_points.clone()), - lookup_bits, params, snarks.clone(), ); @@ -222,8 +226,8 @@ fn bench(c: &mut Criterion) { // do one more time to verify let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Prover, + agg_config, Some(break_points), - lookup_bits, ¶ms, snarks.clone(), ); diff --git a/snark-verifier-sdk/src/halo2/aggregation.rs b/snark-verifier-sdk/src/halo2/aggregation.rs index 9f9ac64a..2d093f7b 100644 --- a/snark-verifier-sdk/src/halo2/aggregation.rs +++ b/snark-verifier-sdk/src/halo2/aggregation.rs @@ -4,8 +4,7 @@ use halo2_base::{ gates::{ builder::{ BaseConfigParams, CircuitBuilderStage, GateThreadBuilder, MultiPhaseThreadBreakPoints, - PublicBaseConfig, RangeCircuitBuilder, RangeWithInstanceCircuitBuilder, - BASE_CONFIG_PARAMS, + PublicBaseConfig, RangeWithInstanceCircuitBuilder, }, flex_gate::GateStrategy, RangeChip, @@ -14,10 +13,7 @@ use halo2_base::{ circuit::{Layouter, SimpleFloorPlanner}, halo2curves::bn256::{Bn256, Fr, G1Affine}, plonk::{self, Circuit, ConstraintSystem, Selector}, - poly::{ - commitment::{Params, ParamsProver}, - kzg::commitment::ParamsKZG, - }, + poly::{commitment::ParamsProver, kzg::commitment::ParamsKZG}, }, utils::ScalarField, AssignedValue, @@ -139,7 +135,7 @@ where /// Same as `FlexGateConfigParams` except we assume a single Phase and default 'Vertical' strategy. /// Also adds `lookup_bits` field. -#[derive(Clone, Copy, Debug, Serialize, Deserialize)] +#[derive(Clone, Copy, Default, Debug, Serialize, Deserialize)] pub struct AggregationConfigParams { pub degree: u32, pub num_advice: usize, @@ -168,6 +164,40 @@ impl From for BaseConfigParams { } } +impl TryFrom<&BaseConfigParams> for AggregationConfigParams { + type Error = &'static str; + + fn try_from(params: &BaseConfigParams) -> Result { + if params.num_advice_per_phase.iter().skip(1).any(|&n| n != 0) { + return Err("AggregationConfigParams only supports 1 phase"); + } + if params.num_lookup_advice_per_phase.iter().skip(1).any(|&n| n != 0) { + return Err("AggregationConfigParams only supports 1 phase"); + } + if params.lookup_bits.is_none() { + return Err("AggregationConfigParams requires lookup_bits"); + } + Ok(Self { + degree: params.k as u32, + num_advice: params.num_advice_per_phase[0], + num_lookup_advice: params.num_lookup_advice_per_phase[0], + num_fixed: params.num_fixed, + lookup_bits: params.lookup_bits.unwrap(), + }) + } +} + +/// Holds virtual contexts for the cells used to verify a collection of snarks +#[derive(Clone, Debug)] +pub struct AggregationCtxBuilder { + /// Virtual region with virtual contexts (columns) + pub builder: GateThreadBuilder, + /// The limbs of the pair of elliptic curve points that need to be verified in a final pairing check. + pub accumulator: Vec>, + // the public instances from previous snarks that were aggregated + pub previous_instances: Vec>>, +} + #[derive(Clone, Debug)] pub struct AggregationCircuit { pub inner: RangeWithInstanceCircuitBuilder, @@ -175,7 +205,7 @@ pub struct AggregationCircuit { // the user can optionally append these to `inner.assigned_instances` to expose them pub previous_instances: Vec>>, // accumulation scheme proof, private input - pub as_proof: Vec, // not sure this needs to be stored, keeping for now + // pub as_proof: Vec, } // trait just so we can have a generic that is either SHPLONK or GWC @@ -201,17 +231,15 @@ pub trait Halo2KzgAccumulationScheme<'a> = PolynomialCommitmentScheme< VerifyingKey = KzgAsVerifyingKey, > + AccumulationSchemeProver>; -impl AggregationCircuit { - /// Given snarks, this creates a circuit and runs the `GateThreadBuilder` to verify all the snarks. - /// By default, the returned circuit has public instances equal to the limbs of the pair of elliptic curve points, referred to as the `accumulator`, that need to be verified in a final pairing check. +impl AggregationCtxBuilder { + /// Given snarks, this runs the `GateThreadBuilder` to verify all the snarks. /// - /// The user can optionally modify the circuit after calling this function to add more instances to `assigned_instances` to expose. + /// Also returns the limbs of the pair of elliptic curve points, referred to as the `accumulator`, that need to be verified in a final pairing check. /// /// Warning: will fail silently if `snarks` were created using a different multi-open scheme than `AS` /// where `AS` can be either [`crate::SHPLONK`] or [`crate::GWC`] (for original PLONK multi-open scheme) pub fn new( - stage: CircuitBuilderStage, - break_points: Option, + witness_gen_only: bool, lookup_bits: usize, params: &ParamsKZG, snarks: impl IntoIterator, @@ -254,11 +282,7 @@ impl AggregationCircuit { }; // create thread builder and run aggregation witness gen - let builder = match stage { - CircuitBuilderStage::Mock => GateThreadBuilder::mock(), - CircuitBuilderStage::Prover => GateThreadBuilder::prover(), - CircuitBuilderStage::Keygen => GateThreadBuilder::keygen(), - }; + let builder = GateThreadBuilder::new(witness_gen_only); // create halo2loader let range = RangeChip::::default(lookup_bits); let fp_chip = FpChip::::new(&range, BITS, LIMBS); @@ -269,7 +293,7 @@ impl AggregationCircuit { aggregate::(&svk, &loader, &snarks, as_proof.as_slice()); let lhs = accumulator.lhs.assigned(); let rhs = accumulator.rhs.assigned(); - let assigned_instances = lhs + let accumulator = lhs .x() .limbs() .iter() @@ -284,73 +308,65 @@ impl AggregationCircuit { let KzgAccumulator { lhs, rhs } = _accumulator; let instances = [lhs.x, lhs.y, rhs.x, rhs.y].map(fe_to_limbs::<_, Fr, LIMBS, BITS>).concat(); - for (lhs, rhs) in instances.iter().zip(assigned_instances.iter()) { + for (lhs, rhs) in instances.iter().zip(accumulator.iter()) { assert_eq!(lhs, rhs.value()); } } let builder = loader.take_ctx(); - let circuit = match stage { - CircuitBuilderStage::Mock => RangeCircuitBuilder::mock(builder), - CircuitBuilderStage::Keygen => RangeCircuitBuilder::keygen(builder), - CircuitBuilderStage::Prover => { - RangeCircuitBuilder::prover(builder, break_points.unwrap()) - } - }; - let inner = RangeWithInstanceCircuitBuilder::new(circuit, assigned_instances); - Self { inner, previous_instances, as_proof } + Self { builder, accumulator, previous_instances } } +} - pub fn public( +impl AggregationCircuit { + /// Given snarks, this creates a circuit and runs the `GateThreadBuilder` to verify all the snarks. + /// By default, the returned circuit has public instances equal to the limbs of the pair of elliptic curve points, referred to as the `accumulator`, that need to be verified in a final pairing check. + /// + /// The user can optionally modify the circuit after calling this function to add more instances to `assigned_instances` to expose. + /// + /// Warning: will fail silently if `snarks` were created using a different multi-open scheme than `AS` + /// where `AS` can be either [`crate::SHPLONK`] or [`crate::GWC`] (for original PLONK multi-open scheme) + pub fn new( stage: CircuitBuilderStage, + agg_config: AggregationConfigParams, break_points: Option, - lookup_bits: usize, params: &ParamsKZG, snarks: impl IntoIterator, - has_prev_accumulator: bool, ) -> Self where AS: for<'a> Halo2KzgAccumulationScheme<'a>, { - let mut private = Self::new::(stage, break_points, lookup_bits, params, snarks); - private.expose_previous_instances(has_prev_accumulator); - private - } - - // this function is for convenience - /// `params` should be the universal trusted setup to be used for the aggregation circuit, not the one used to generate the previous snarks, although we assume both use the same generator g[0] - pub fn keygen(params: &ParamsKZG, snarks: impl IntoIterator) -> Self - where - AS: for<'a> Halo2KzgAccumulationScheme<'a>, - { - let lookup_bits = BASE_CONFIG_PARAMS - .with(|conf| conf.borrow().lookup_bits) - .unwrap_or(params.k() as usize - 1); - let circuit = - Self::new::(CircuitBuilderStage::Keygen, None, lookup_bits, params, snarks); - circuit.config(params.k(), Some(10)); - circuit + let AggregationCtxBuilder { builder, accumulator, previous_instances } = + AggregationCtxBuilder::new::( + stage == CircuitBuilderStage::Prover, + agg_config.lookup_bits, + params, + snarks, + ); + let inner = RangeWithInstanceCircuitBuilder::from_stage( + stage, + builder, + agg_config.into(), + break_points, + accumulator, + ); + Self { inner, previous_instances } } - // this function is for convenience - pub fn prover( + pub fn public( + stage: CircuitBuilderStage, + agg_config: AggregationConfigParams, + break_points: Option, params: &ParamsKZG, snarks: impl IntoIterator, - break_points: MultiPhaseThreadBreakPoints, + has_prev_accumulator: bool, ) -> Self where AS: for<'a> Halo2KzgAccumulationScheme<'a>, { - let lookup_bits = BASE_CONFIG_PARAMS - .with(|conf| conf.borrow().lookup_bits) - .unwrap_or(params.k() as usize - 1); - Self::new::( - CircuitBuilderStage::Prover, - Some(break_points), - lookup_bits, - params, - snarks, - ) + let mut private = Self::new::(stage, agg_config, break_points, params, snarks); + private.expose_previous_instances(has_prev_accumulator); + private } /// Re-expose the previous public instances of aggregated snarks again. @@ -363,12 +379,12 @@ impl AggregationCircuit { } } - pub fn as_proof(&self) -> &[u8] { - &self.as_proof[..] - } - - pub fn config(&self, k: u32, minimum_rows: Option) -> BaseConfigParams { - self.inner.config(k, minimum_rows) + /// Auto-configure the circuit and change the circuit's internal configuration parameters. + pub fn config(&mut self, k: u32, minimum_rows: Option) -> BaseConfigParams { + let mut new_config = self.inner.circuit.0.builder.borrow().config(k as usize, minimum_rows); + new_config.lookup_bits = self.inner.circuit.0.config_params.lookup_bits; + self.inner.circuit.0.config_params = new_config.clone(); + new_config } pub fn break_points(&self) -> MultiPhaseThreadBreakPoints { @@ -401,13 +417,25 @@ impl CircuitExt for RangeWithInstanceCircuitBuilder { impl Circuit for AggregationCircuit { type Config = PublicBaseConfig; type FloorPlanner = SimpleFloorPlanner; + type Params = AggregationConfigParams; + + fn params(&self) -> Self::Params { + (&self.inner.circuit.0.config_params).try_into().unwrap() + } fn without_witnesses(&self) -> Self { unimplemented!() } - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - RangeWithInstanceCircuitBuilder::configure(meta) + fn configure_with_params( + meta: &mut ConstraintSystem, + params: Self::Params, + ) -> Self::Config { + RangeWithInstanceCircuitBuilder::configure_with_params(meta, params.into()) + } + + fn configure(_: &mut ConstraintSystem) -> Self::Config { + unreachable!() } fn synthesize( diff --git a/snark-verifier-sdk/src/lib.rs b/snark-verifier-sdk/src/lib.rs index 07a15bc7..40401a4c 100644 --- a/snark-verifier-sdk/src/lib.rs +++ b/snark-verifier-sdk/src/lib.rs @@ -78,13 +78,14 @@ pub trait CircuitExt: Circuit { } } -pub fn read_pk>(path: &Path) -> io::Result> { - read_pk_with_capacity::(BUFFER_SIZE, path) +pub fn read_pk>(path: &Path, params: C::Params) -> io::Result> { + read_pk_with_capacity::(BUFFER_SIZE, path, params) } pub fn read_pk_with_capacity>( capacity: usize, path: impl AsRef, + params: C::Params, ) -> io::Result> { let f = File::open(path.as_ref())?; #[cfg(feature = "display")] @@ -97,7 +98,8 @@ pub fn read_pk_with_capacity>( // let initial_buffer_size = f.metadata().map(|m| m.len() as usize + 1).unwrap_or(0); // let mut bufreader = Vec::with_capacity(initial_buffer_size); // f.read_to_end(&mut bufreader)?; - let pk = ProvingKey::read::<_, C>(&mut bufreader, SerdeFormat::RawBytesUnchecked).unwrap(); + let pk = + ProvingKey::read::<_, C>(&mut bufreader, SerdeFormat::RawBytesUnchecked, params).unwrap(); #[cfg(feature = "display")] end_timer!(read_time); @@ -112,7 +114,7 @@ pub fn gen_pk>( path: Option<&Path>, ) -> ProvingKey { if let Some(path) = path { - if let Ok(pk) = read_pk::(path) { + if let Ok(pk) = read_pk::(path, circuit.params()) { return pk; } } diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index 313fd038..5606df37 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -1,25 +1,28 @@ [package] name = "snark-verifier" -version = "0.1.1" +version = "0.1.2" edition = "2021" [dependencies] -itertools = "0.10.5" -lazy_static = "1.4.0" -num-bigint = "0.4.3" +itertools = "0.11" +lazy_static = "1.4" +num-bigint = "0.4" num-integer = "0.1.45" num-traits = "0.2.15" hex = "0.4" rand = "0.8" serde = { version = "1.0", features = ["derive"] } +pairing = { version = "0.23" } # Use halo2-base as non-optional dependency because it re-exports halo2_proofs, halo2curves, and poseidon, using different repos based on feature flag "halo2-axiom" or "halo2-pse" halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } # This is Scroll's audited poseidon circuit. We only use it for the Native Poseidon spec. We do not use the halo2 circuit at all (and it wouldn't even work because the halo2_proofs tag is not compatbile). -poseidon-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit.git", rev = "50015b7" } +# We forked it to upgrade to ff v0.13 and removed the circuit module +poseidon-rs = { git = "https://github.com/axiom-crypto/poseidon-circuit.git", rev = "1aee4a1" } +# poseidon-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit.git", rev = "50015b7" } # parallel -rayon = { version = "1.7.0", optional = true } +rayon = { version = "1.7", optional = true } # loader_evm sha3 = { version = "0.10.8", optional = true } diff --git a/snark-verifier/examples/evm-verifier-with-accumulator.rs b/snark-verifier/examples/evm-verifier-with-accumulator.rs index 4ffa6459..41493efa 100644 --- a/snark-verifier/examples/evm-verifier-with-accumulator.rs +++ b/snark-verifier/examples/evm-verifier-with-accumulator.rs @@ -1,6 +1,6 @@ use aggregation::{AggregationCircuit, AggregationConfigParams}; use halo2_base::{ - gates::builder::{set_lookup_bits, CircuitBuilderStage}, + gates::builder::{BaseConfigParams, CircuitBuilderStage}, halo2_proofs, utils::fs::gen_srs, }; @@ -300,7 +300,7 @@ mod aggregation { As::verify(&Default::default(), &accumulators, &proof).unwrap() } - #[derive(serde::Serialize, serde::Deserialize)] + #[derive(serde::Serialize, serde::Deserialize, Default)] pub struct AggregationConfigParams { pub degree: u32, pub num_advice: usize, @@ -318,8 +318,8 @@ mod aggregation { impl AggregationCircuit { pub fn new( stage: CircuitBuilderStage, + config_params: BaseConfigParams, break_points: Option, - lookup_bits: usize, params_g0: G1Affine, snarks: impl IntoIterator, ) -> Self { @@ -355,13 +355,9 @@ mod aggregation { }; // create thread builder and run aggregation witness gen - let builder = match stage { - CircuitBuilderStage::Mock => GateThreadBuilder::mock(), - CircuitBuilderStage::Prover => GateThreadBuilder::prover(), - CircuitBuilderStage::Keygen => GateThreadBuilder::keygen(), - }; + let builder = GateThreadBuilder::from_stage(stage); // create halo2loader - let range = RangeChip::::default(lookup_bits); + let range = RangeChip::::default(config_params.lookup_bits.unwrap()); let fp_chip = FpChip::::new(&range, BITS, LIMBS); let ecc_chip = BaseFieldEccChip::new(&fp_chip); let loader = Halo2Loader::new(ecc_chip, builder); @@ -391,24 +387,25 @@ mod aggregation { } let builder = loader.take_ctx(); - let inner = match stage { - CircuitBuilderStage::Mock => { - RangeWithInstanceCircuitBuilder::mock(builder, assigned_instances) - } - CircuitBuilderStage::Keygen => { - RangeWithInstanceCircuitBuilder::keygen(builder, assigned_instances) - } - CircuitBuilderStage::Prover => RangeWithInstanceCircuitBuilder::prover( - builder, - assigned_instances, - break_points.unwrap(), - ), - }; + let inner = RangeWithInstanceCircuitBuilder::from_stage( + stage, + builder, + config_params, + break_points, + assigned_instances, + ); Self { inner, as_proof } } - pub fn config(&self, k: u32, minimum_rows: Option) -> BaseConfigParams { - self.inner.circuit.0.builder.borrow().config(k as usize, minimum_rows) + pub fn config( + &self, + k: u32, + minimum_rows: Option, + lookup_bits: usize, + ) -> BaseConfigParams { + let mut params = self.inner.circuit.0.builder.borrow().config(k as usize, minimum_rows); + params.lookup_bits = Some(lookup_bits); + params } pub fn break_points(&self) -> MultiPhaseThreadBreakPoints { @@ -432,13 +429,25 @@ mod aggregation { impl Circuit for AggregationCircuit { type Config = PublicBaseConfig; type FloorPlanner = SimpleFloorPlanner; + type Params = BaseConfigParams; + + fn params(&self) -> Self::Params { + self.inner.circuit.params() + } + + fn configure_with_params( + meta: &mut plonk::ConstraintSystem, + params: Self::Params, + ) -> Self::Config { + RangeWithInstanceCircuitBuilder::configure_with_params(meta, params) + } fn without_witnesses(&self) -> Self { unimplemented!() } - fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { - RangeWithInstanceCircuitBuilder::configure(meta) + fn configure(_: &mut plonk::ConstraintSystem) -> Self::Config { + unimplemented!() } fn synthesize( @@ -574,15 +583,23 @@ fn main() { File::open(path).unwrap_or_else(|e| panic!("{path} does not exist: {e:?}")), ) .unwrap(); - set_lookup_bits(agg_config.lookup_bits); - let agg_circuit = AggregationCircuit::new( + let mut config_params = BaseConfigParams { + k: agg_config.degree as usize, + strategy: Default::default(), + num_advice_per_phase: vec![agg_config.num_advice], + num_lookup_advice_per_phase: vec![agg_config.num_lookup_advice], + num_fixed: agg_config.num_fixed, + lookup_bits: Some(agg_config.lookup_bits), + }; + let mut agg_circuit = AggregationCircuit::new( CircuitBuilderStage::Mock, + config_params, None, - agg_config.lookup_bits, params_app.get_g()[0], snarks.clone(), ); - agg_circuit.config(agg_config.degree, Some(6)); + config_params = agg_circuit.config(agg_config.degree, Some(6), agg_config.lookup_bits); + agg_circuit.inner.circuit.0.config_params = config_params.clone(); #[cfg(debug_assertions)] { MockProver::run(agg_config.degree, &agg_circuit, agg_circuit.instances()) @@ -605,8 +622,8 @@ fn main() { let agg_circuit = AggregationCircuit::new( CircuitBuilderStage::Prover, + config_params, Some(break_points), - agg_config.lookup_bits, params_app.get_g()[0], snarks, ); diff --git a/snark-verifier/examples/recursion.rs b/snark-verifier/examples/recursion.rs index 7415e1ab..b469a51a 100644 --- a/snark-verifier/examples/recursion.rs +++ b/snark-verifier/examples/recursion.rs @@ -3,7 +3,7 @@ use ark_std::{end_timer, start_timer}; use common::*; use halo2_base::gates::builder::BaseConfigParams; -use halo2_base::gates::{builder::BASE_CONFIG_PARAMS, flex_gate::GateStrategy}; +use halo2_base::gates::flex_gate::GateStrategy; use halo2_base::halo2_proofs; use halo2_base::utils::fs::gen_srs; use halo2_proofs::{ @@ -12,11 +12,10 @@ use halo2_proofs::{ halo2curves::{ bn256::{Bn256, Fr, G1Affine}, group::ff::Field, - FieldExt, }, plonk::{ - self, create_proof, keygen_pk, keygen_vk, Circuit, ConstraintSystem, Error, ProvingKey, - Selector, VerifyingKey, + create_proof, keygen_pk, keygen_vk, Circuit, ConstraintSystem, Error, ProvingKey, Selector, + VerifyingKey, }, poly::{ commitment::ParamsProver, @@ -192,19 +191,38 @@ mod common { pub fn gen_dummy_snark>( params: &ParamsKZG, vk: Option<&VerifyingKey>, - ) -> Snark { - struct CsProxy(PhantomData<(F, C)>); + config_params: ConcreteCircuit::Params, + ) -> Snark + where + ConcreteCircuit::Params: Clone, + { + struct CsProxy>(C::Params, PhantomData<(F, C)>); - impl> Circuit for CsProxy { + impl> Circuit for CsProxy + where + C::Params: Clone, + { type Config = C::Config; type FloorPlanner = C::FloorPlanner; + type Params = C::Params; + + fn params(&self) -> Self::Params { + self.0.clone() + } fn without_witnesses(&self) -> Self { - CsProxy(PhantomData) + CsProxy(self.0.clone(), PhantomData) + } + + fn configure_with_params( + meta: &mut ConstraintSystem, + params: Self::Params, + ) -> Self::Config { + C::configure_with_params(meta, params) } - fn configure(meta: &mut ConstraintSystem) -> Self::Config { - C::configure(meta) + fn configure(_: &mut ConstraintSystem) -> Self::Config { + unreachable!() } fn synthesize( @@ -227,9 +245,9 @@ mod common { } } - let dummy_vk = vk - .is_none() - .then(|| keygen_vk(params, &CsProxy::(PhantomData)).unwrap()); + let dummy_vk = vk.is_none().then(|| { + keygen_vk(params, &CsProxy::(config_params, PhantomData)).unwrap() + }); let protocol = compile( params, vk.or(dummy_vk.as_ref()).unwrap(), @@ -326,10 +344,7 @@ mod application { mod recursion { use halo2_base::{ gates::{ - builder::{ - GateThreadBuilder, PublicBaseConfig, RangeWithInstanceCircuitBuilder, - BASE_CONFIG_PARAMS, - }, + builder::{GateThreadBuilder, PublicBaseConfig, RangeWithInstanceCircuitBuilder}, GateInstructions, RangeChip, RangeInstructions, }, AssignedValue, @@ -456,6 +471,7 @@ mod recursion { round: usize, instances: Vec, as_proof: Vec, + lookup_bits: usize, inner: RangeWithInstanceCircuitBuilder, } @@ -473,6 +489,7 @@ mod recursion { initial_state: Fr, state: Fr, round: usize, + config_params: BaseConfigParams, ) -> Self { let svk = params.get_g()[0].into(); let default_accumulator = KzgAccumulator::new(params.get_g()[1], params.get_g()[0]); @@ -528,17 +545,25 @@ mod recursion { .collect(); let builder = GateThreadBuilder::mock(); - let inner = RangeWithInstanceCircuitBuilder::mock(builder, vec![]); - let mut circuit = - Self { svk, default_accumulator, app, previous, round, instances, as_proof, inner }; + let lookup_bits = config_params.lookup_bits.unwrap(); + let inner = RangeWithInstanceCircuitBuilder::mock(builder, config_params, vec![]); + let mut circuit = Self { + svk, + default_accumulator, + app, + previous, + round, + instances, + as_proof, + inner, + lookup_bits, + }; circuit.build(); circuit } fn build(&mut self) { - let lookup_bits = - BASE_CONFIG_PARAMS.with(|params| params.borrow().lookup_bits.unwrap()); - let range = RangeChip::::default(lookup_bits); + let range = RangeChip::::default(self.lookup_bits); let main_gate = range.gate(); let mut builder = GateThreadBuilder::mock(); let ctx = &mut builder; @@ -626,8 +651,12 @@ mod recursion { ); } - fn initial_snark(params: &ParamsKZG, vk: Option<&VerifyingKey>) -> Snark { - let mut snark = gen_dummy_snark::(params, vk); + fn initial_snark( + params: &ParamsKZG, + vk: Option<&VerifyingKey>, + config_params: BaseConfigParams, + ) -> Snark { + let mut snark = gen_dummy_snark::(params, vk, config_params); let g = params.get_g(); snark.instances = vec![[g[1].x, g[1].y, g[0].x, g[0].y] .into_iter() @@ -658,13 +687,25 @@ mod recursion { impl Circuit for RecursionCircuit { type Config = PublicBaseConfig; type FloorPlanner = SimpleFloorPlanner; + type Params = BaseConfigParams; + + fn params(&self) -> Self::Params { + self.inner.circuit.params() + } fn without_witnesses(&self) -> Self { unimplemented!() } - fn configure(meta: &mut plonk::ConstraintSystem) -> Self::Config { - RangeWithInstanceCircuitBuilder::configure(meta) + fn configure_with_params( + meta: &mut ConstraintSystem, + params: Self::Params, + ) -> Self::Config { + RangeWithInstanceCircuitBuilder::configure_with_params(meta, params) + } + + fn configure(_: &mut ConstraintSystem) -> Self::Config { + unreachable!() } fn synthesize( @@ -699,14 +740,20 @@ mod recursion { recursion_params: &ParamsKZG, app_params: &ParamsKZG, app_vk: &VerifyingKey, - ) -> ProvingKey { + recursion_config: BaseConfigParams, + app_config: ConcreteCircuit::Params, + ) -> ProvingKey + where + ConcreteCircuit::Params: Clone, + { let recursion = RecursionCircuit::new( recursion_params, - gen_dummy_snark::(app_params, Some(app_vk)), - RecursionCircuit::initial_snark(recursion_params, None), + gen_dummy_snark::(app_params, Some(app_vk), app_config), + RecursionCircuit::initial_snark(recursion_params, None, recursion_config.clone()), Fr::zero(), Fr::zero(), 0, + recursion_config, ); // we cannot auto-configure the circuit because dummy_snark must know the configuration beforehand // uncomment the following line only in development to test and print out the optimal configuration ahead of time @@ -721,11 +768,15 @@ mod recursion { recursion_pk: &ProvingKey, initial_state: Fr, inputs: Vec, + config_params: BaseConfigParams, ) -> (Fr, Snark) { let mut state = initial_state; let mut app = ConcreteCircuit::new(state); - let mut previous = - RecursionCircuit::initial_snark(recursion_params, Some(recursion_pk.get_vk())); + let mut previous = RecursionCircuit::initial_snark( + recursion_params, + Some(recursion_pk.get_vk()), + config_params.clone(), + ); for (round, input) in inputs.into_iter().enumerate() { state = app.state_transition(input); println!("Generate app snark"); @@ -737,6 +788,7 @@ mod recursion { initial_state, state, round, + config_params.clone(), ); println!("Generate recursion snark"); previous = gen_snark(recursion_params, recursion_pk, recursion); @@ -752,16 +804,14 @@ fn main() { serde_json::from_reader(fs::File::open("configs/example_recursion.json").unwrap()).unwrap(); let k = recursion_config.degree; let recursion_params = gen_srs(k); - BASE_CONFIG_PARAMS.with(|params| { - *params.borrow_mut() = BaseConfigParams { - strategy: GateStrategy::Vertical, - k: k as usize, - num_advice_per_phase: vec![recursion_config.num_advice], - num_lookup_advice_per_phase: vec![recursion_config.num_lookup_advice], - num_fixed: recursion_config.num_fixed, - lookup_bits: Some(recursion_config.lookup_bits), - } - }); + let config_params = BaseConfigParams { + strategy: GateStrategy::Vertical, + k: k as usize, + num_advice_per_phase: vec![recursion_config.num_advice], + num_lookup_advice_per_phase: vec![recursion_config.num_lookup_advice], + num_fixed: recursion_config.num_fixed, + lookup_bits: Some(recursion_config.lookup_bits), + }; let app_pk = gen_pk(&app_params, &application::Square::default()); @@ -770,6 +820,8 @@ fn main() { &recursion_params, &app_params, app_pk.get_vk(), + config_params.clone(), + (), ); end_timer!(pk_time); @@ -782,9 +834,10 @@ fn main() { &recursion_pk, Fr::from(2u64), vec![(); num_round], + config_params.clone(), ); end_timer!(pf_time); - assert_eq!(final_state, Fr::from(2u64).pow(&[1 << num_round, 0, 0, 0])); + assert_eq!(final_state, Fr::from(2u64).pow([1 << num_round])); { let dk = diff --git a/snark-verifier/src/loader.rs b/snark-verifier/src/loader.rs index 77a8f54b..a3637f08 100644 --- a/snark-verifier/src/loader.rs +++ b/snark-verifier/src/loader.rs @@ -122,12 +122,12 @@ pub trait ScalarLoader { /// Load `zero` as constant. fn load_zero(&self) -> Self::LoadedScalar { - self.load_const(&F::zero()) + self.load_const(&F::ZERO) } /// Load `one` as constant. fn load_one(&self) -> Self::LoadedScalar { - self.load_const(&F::one()) + self.load_const(&F::ONE) } /// Assert lhs and rhs field elements are equal. @@ -145,13 +145,13 @@ pub trait ScalarLoader { let loader = values.first().unwrap().1.loader(); iter::empty() - .chain(if constant == F::zero() { + .chain(if constant == F::ZERO { None } else { Some(Cow::Owned(loader.load_const(&constant))) }) .chain(values.iter().map(|&(coeff, value)| { - if coeff == F::one() { + if coeff == F::ONE { Cow::Borrowed(value) } else { Cow::Owned(loader.load_const(&coeff) * value) @@ -174,9 +174,9 @@ pub trait ScalarLoader { let loader = values.first().unwrap().1.loader(); iter::empty() - .chain(if constant == F::zero() { None } else { Some(loader.load_const(&constant)) }) + .chain(if constant == F::ZERO { None } else { Some(loader.load_const(&constant)) }) .chain(values.iter().map(|&(coeff, lhs, rhs)| { - if coeff == F::one() { + if coeff == F::ONE { lhs.clone() * rhs } else { loader.load_const(&coeff) * lhs * rhs @@ -188,20 +188,20 @@ pub trait ScalarLoader { /// Sum field elements with coefficients. fn sum_with_coeff(&self, values: &[(F, &Self::LoadedScalar)]) -> Self::LoadedScalar { - self.sum_with_coeff_and_const(values, F::zero()) + self.sum_with_coeff_and_const(values, F::ZERO) } /// Sum field elements and constant. fn sum_with_const(&self, values: &[&Self::LoadedScalar], constant: F) -> Self::LoadedScalar { self.sum_with_coeff_and_const( - &values.iter().map(|&value| (F::one(), value)).collect_vec(), + &values.iter().map(|&value| (F::ONE, value)).collect_vec(), constant, ) } /// Sum field elements. fn sum(&self, values: &[&Self::LoadedScalar]) -> Self::LoadedScalar { - self.sum_with_const(values, F::zero()) + self.sum_with_const(values, F::ZERO) } /// Sum product of field elements with coefficients. @@ -209,7 +209,7 @@ pub trait ScalarLoader { &self, values: &[(F, &Self::LoadedScalar, &Self::LoadedScalar)], ) -> Self::LoadedScalar { - self.sum_products_with_coeff_and_const(values, F::zero()) + self.sum_products_with_coeff_and_const(values, F::ZERO) } /// Sum product of field elements and constant. @@ -219,7 +219,7 @@ pub trait ScalarLoader { constant: F, ) -> Self::LoadedScalar { self.sum_products_with_coeff_and_const( - &values.iter().map(|&(lhs, rhs)| (F::one(), lhs, rhs)).collect_vec(), + &values.iter().map(|&(lhs, rhs)| (F::ONE, lhs, rhs)).collect_vec(), constant, ) } @@ -229,7 +229,7 @@ pub trait ScalarLoader { &self, values: &[(&Self::LoadedScalar, &Self::LoadedScalar)], ) -> Self::LoadedScalar { - self.sum_products_with_const(values, F::zero()) + self.sum_products_with_const(values, F::ZERO) } /// Product of field elements. diff --git a/snark-verifier/src/loader/evm/loader.rs b/snark-verifier/src/loader/evm/loader.rs index 98ca5ca4..bfb37c8c 100644 --- a/snark-verifier/src/loader/evm/loader.rs +++ b/snark-verifier/src/loader/evm/loader.rs @@ -684,8 +684,8 @@ impl> ScalarLoader for Rc { } let push_addend = |(coeff, value): &(F, &Scalar)| { - assert_ne!(*coeff, F::zero()); - match (*coeff == F::one(), &value.value) { + assert_ne!(*coeff, F::ZERO); + match (*coeff == F::ONE, &value.value) { (true, _) => self.push(value), (false, Value::Constant(value)) => self.push( &self.scalar(Value::Constant(fe_to_u256(*coeff * u256_to_fe::(*value)))), @@ -699,7 +699,7 @@ impl> ScalarLoader for Rc { }; let mut values = values.iter(); - let initial_value = if constant == F::zero() { + let initial_value = if constant == F::ZERO { push_addend(values.next().unwrap()) } else { self.push(&self.scalar(Value::Constant(fe_to_u256(constant)))) @@ -733,8 +733,8 @@ impl> ScalarLoader for Rc { } let push_addend = |(coeff, lhs, rhs): &(F, &Scalar, &Scalar)| { - assert_ne!(*coeff, F::zero()); - match (*coeff == F::one(), &lhs.value, &rhs.value) { + assert_ne!(*coeff, F::ZERO); + match (*coeff == F::ONE, &lhs.value, &rhs.value) { (_, Value::Constant(lhs), Value::Constant(rhs)) => { self.push(&self.scalar(Value::Constant(fe_to_u256( *coeff * u256_to_fe::(*lhs) * u256_to_fe::(*rhs), @@ -764,7 +764,7 @@ impl> ScalarLoader for Rc { }; let mut values = values.iter(); - let initial_value = if constant == F::zero() { + let initial_value = if constant == F::ZERO { push_addend(values.next().unwrap()) } else { self.push(&self.scalar(Value::Constant(fe_to_u256(constant)))) diff --git a/snark-verifier/src/loader/evm/test/tui.rs b/snark-verifier/src/loader/evm/test/tui.rs index 328082c7..9bd68bb9 100644 --- a/snark-verifier/src/loader/evm/test/tui.rs +++ b/snark-verifier/src/loader/evm/test/tui.rs @@ -45,12 +45,7 @@ impl Tui { let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend).unwrap(); terminal.hide_cursor().unwrap(); - Tui { - debug_arena, - terminal, - key_buffer: String::new(), - current_step, - } + Tui { debug_arena, terminal, key_buffer: String::new(), current_step } } pub fn start(mut self) { @@ -91,11 +86,8 @@ impl Tui { let mut draw_memory: DrawMemory = DrawMemory::default(); let debug_call = &self.debug_arena; - let mut opcode_list: Vec = debug_call[0] - .1 - .iter() - .map(|step| step.pretty_opcode()) - .collect(); + let mut opcode_list: Vec = + debug_call[0].1.iter().map(|step| step.pretty_opcode()).collect(); let mut last_index = 0; let mut stack_labels = false; @@ -385,12 +377,8 @@ impl Tui { if let [op_pane, stack_pane, memory_pane] = Layout::default() .direction(Direction::Vertical) .constraints( - [ - Constraint::Ratio(1, 3), - Constraint::Ratio(1, 3), - Constraint::Ratio(1, 3), - ] - .as_ref(), + [Constraint::Ratio(1, 3), Constraint::Ratio(1, 3), Constraint::Ratio(1, 3)] + .as_ref(), ) .split(app)[..] { @@ -412,14 +400,7 @@ impl Tui { stack_labels, draw_memory, ); - Tui::draw_memory( - f, - debug_steps, - current_step, - memory_pane, - mem_utf, - draw_memory, - ); + Tui::draw_memory(f, debug_steps, current_step, memory_pane, mem_utf, draw_memory); } else { panic!("unable to create vertical panes") } @@ -536,15 +517,11 @@ impl Tui { let prev_start = draw_memory.current_startline; let abs_min_start = 0; let abs_max_start = (opcode_list.len() as i32 - 1) - (height / 2); - let mut min_start = max( - current_step as i32 - height + extra_top_lines, - abs_min_start, - ) as usize; + let mut min_start = + max(current_step as i32 - height + extra_top_lines, abs_min_start) as usize; - let mut max_start = max( - min(current_step as i32 - extra_top_lines, abs_max_start), - abs_min_start, - ) as usize; + let mut max_start = + max(min(current_step as i32 - extra_top_lines, abs_max_start), abs_min_start) as usize; if min_start > max_start { std::mem::swap(&mut min_start, &mut max_start); @@ -559,18 +536,11 @@ impl Tui { } draw_memory.current_startline = display_start; - let max_pc_len = debug_steps - .iter() - .fold(0, |max_val, val| val.pc.max(max_val)) - .to_string() - .len(); + let max_pc_len = + debug_steps.iter().fold(0, |max_val, val| val.pc.max(max_val)).to_string().len(); let mut add_new_line = |line_number| { - let bg_color = if line_number == current_step { - Color::DarkGray - } else { - Color::Reset - }; + let bg_color = if line_number == current_step { Color::DarkGray } else { Color::Reset }; let line_number_format = if line_number == current_step { let step: &DebugStep = &debug_steps[line_number]; @@ -598,9 +568,8 @@ impl Tui { add_new_line(number); } add_new_line(opcode_list.len()); - let paragraph = Paragraph::new(text_output) - .block(block_source_code) - .wrap(Wrap { trim: true }); + let paragraph = + Paragraph::new(text_output).block(block_source_code).wrap(Wrap { trim: true }); f.render_widget(paragraph, area); } @@ -610,12 +579,11 @@ impl Tui { current_step: usize, area: Rect, stack_labels: bool, - draw_memory: &mut DrawMemory, + draw_memory: &DrawMemory, ) { let stack = &debug_steps[current_step].stack; - let stack_space = Block::default() - .title(format!("Stack: {}", stack.len())) - .borders(Borders::ALL); + let stack_space = + Block::default().title(format!("Stack: {}", stack.len())).borders(Borders::ALL); let min_len = usize::max(format!("{}", stack.len()).len(), 2); let indices_affected = stack_indices_affected(debug_steps[current_step].instruction.0); @@ -626,12 +594,10 @@ impl Tui { .enumerate() .skip(draw_memory.current_stack_startline) .map(|(i, stack_item)| { - let affected = indices_affected - .iter() - .find(|(affected_index, _name)| *affected_index == i); + let affected = + indices_affected.iter().find(|(affected_index, _name)| *affected_index == i); let mut words: Vec = (0..32) - .into_iter() .rev() .map(|i| stack_item.byte(i)) .map(|byte| { @@ -667,9 +633,7 @@ impl Tui { }) .collect(); - let paragraph = Paragraph::new(text) - .block(stack_space) - .wrap(Wrap { trim: true }); + let paragraph = Paragraph::new(text).block(stack_space).wrap(Wrap { trim: true }); f.render_widget(paragraph, area); } @@ -679,14 +643,11 @@ impl Tui { current_step: usize, area: Rect, mem_utf8: bool, - draw_mem: &mut DrawMemory, + draw_mem: &DrawMemory, ) { let memory = &debug_steps[current_step].memory; let stack_space = Block::default() - .title(format!( - "Memory (max expansion: {} bytes)", - memory.effective_len() - )) + .title(format!("Memory (max expansion: {} bytes)", memory.effective_len())) .borders(Borders::ALL); let memory = memory.data(); let max_i = memory.len() / 32; @@ -773,9 +734,7 @@ impl Tui { Spans::from(spans) }) .collect(); - let paragraph = Paragraph::new(text) - .block(stack_space) - .wrap(Wrap { trim: true }); + let paragraph = Paragraph::new(text).block(stack_space).wrap(Wrap { trim: true }); f.render_widget(paragraph, area); } } @@ -884,13 +843,7 @@ fn stack_indices_affected(op: u8) -> Vec<(usize, &'static str)> { 0xa0 => vec![(0, "offset"), (1, "length")], 0xa1 => vec![(0, "offset"), (1, "length"), (2, "topic")], 0xa2 => vec![(0, "offset"), (1, "length"), (2, "topic1"), (3, "topic2")], - 0xa3 => vec![ - (0, "offset"), - (1, "length"), - (2, "topic1"), - (3, "topic2"), - (4, "topic3"), - ], + 0xa3 => vec![(0, "offset"), (1, "length"), (2, "topic1"), (3, "topic2"), (4, "topic3")], 0xa4 => vec![ (0, "offset"), (1, "length"), diff --git a/snark-verifier/src/loader/evm/util.rs b/snark-verifier/src/loader/evm/util.rs index a84df4c3..5df077f6 100644 --- a/snark-verifier/src/loader/evm/util.rs +++ b/snark-verifier/src/loader/evm/util.rs @@ -74,7 +74,7 @@ pub fn modulus() -> U256 where F: PrimeField, { - U256::from_little_endian((-F::one()).to_repr().as_ref()) + 1 + U256::from_little_endian((-F::ONE).to_repr().as_ref()) + 1 } /// Encode instances and proof into calldata. diff --git a/snark-verifier/src/loader/evm/util/executor.rs b/snark-verifier/src/loader/evm/util/executor.rs index a7697a0e..17062028 100644 --- a/snark-verifier/src/loader/evm/util/executor.rs +++ b/snark-verifier/src/loader/evm/util/executor.rs @@ -47,13 +47,8 @@ fn get_create2_address_from_hash( salt: [u8; 32], init_code_hash: impl Into, ) -> Address { - let bytes = [ - &[0xff], - from.into().as_bytes(), - salt.as_slice(), - init_code_hash.into().as_ref(), - ] - .concat(); + let bytes = + [&[0xff], from.into().as_bytes(), salt.as_slice(), init_code_hash.into().as_ref()].concat(); let hash = keccak256(bytes); @@ -87,11 +82,7 @@ struct LogCollector { impl Inspector for LogCollector { fn log(&mut self, _: &mut EVMData<'_, DB>, address: &Address, topics: &[H256], data: &Bytes) { - self.logs.push(Log { - address: *address, - topics: topics.to_vec(), - data: data.clone(), - }); + self.logs.push(Log { address: *address, topics: topics.to_vec(), data: data.clone() }); } fn call( @@ -114,6 +105,7 @@ pub enum CallKind { Create2, } +#[allow(clippy::derivable_impls)] impl Default for CallKind { fn default() -> Self { CallKind::Call @@ -284,29 +276,15 @@ impl Debugger { fn enter(&mut self, depth: usize, address: Address, kind: CallKind) { self.context = address; - self.head = self.arena.push_node(DebugNode { - depth, - address, - kind, - ..Default::default() - }); + self.head = self.arena.push_node(DebugNode { depth, address, kind, ..Default::default() }); } fn exit(&mut self) { if let Some(parent_id) = self.arena.arena[self.head].parent { - let DebugNode { - depth, - address, - kind, - .. - } = self.arena.arena[parent_id]; + let DebugNode { depth, address, kind, .. } = self.arena.arena[parent_id]; self.context = address; - self.head = self.arena.push_node(DebugNode { - depth, - address, - kind, - ..Default::default() - }); + self.head = + self.arena.push_node(DebugNode { depth, address, kind, ..Default::default() }); } } } @@ -324,11 +302,7 @@ impl Inspector for Debugger { let opcode_infos = spec_opcode_gas(data.env.cfg.spec_id); let opcode_info = &opcode_infos[op as usize]; - let push_size = if opcode_info.is_push() { - (op - opcode::PUSH1 + 1) as usize - } else { - 0 - }; + let push_size = if opcode_info.is_push() { (op - opcode::PUSH1 + 1) as usize } else { 0 }; let push_bytes = match push_size { 0 => None, n => { @@ -394,12 +368,7 @@ impl Inspector for Debugger { CallKind::Create, ); - ( - Return::Continue, - None, - Gas::new(call.gas_limit), - Bytes::new(), - ) + (Return::Continue, None, Gas::new(call.gas_limit), Bytes::new()) } fn create_end( @@ -619,12 +588,7 @@ impl Inspector for InspectorStack { } ); - ( - Return::Continue, - None, - Gas::new(call.gas_limit), - Bytes::new(), - ) + (Return::Continue, None, Gas::new(call.gas_limit), Bytes::new()) } fn create_end( @@ -741,11 +705,7 @@ pub struct Executor { impl Executor { fn new(debugger: bool, gas_limit: U256) -> Self { - Executor { - db: InMemoryDB::default(), - debugger, - gas_limit, - } + Executor { db: InMemoryDB::default(), debugger, gas_limit } } pub fn db_mut(&mut self) -> &mut InMemoryDB { @@ -757,16 +717,8 @@ impl Executor { let result = self.call_raw_with_env(env); self.commit(&result); - let RawCallResult { - exit_reason, - out, - gas_used, - gas_refunded, - logs, - debug, - env, - .. - } = result; + let RawCallResult { exit_reason, out, gas_used, gas_refunded, logs, debug, env, .. } = + result; let address = match (exit_reason, out) { (return_ok!(), TransactOut::Create(_, Some(address))) => Some(address), @@ -801,13 +753,7 @@ impl Executor { let result = evm_inner::<_, true>(&mut env, &mut self.db.clone(), &mut inspector).transact(); let (exec_result, state_changeset) = result; - let ExecutionResult { - exit_reason, - gas_refunded, - gas_used, - out, - .. - } = exec_result; + let ExecutionResult { exit_reason, gas_refunded, gas_used, out, .. } = exec_result; let result = match out { TransactOut::Call(ref data) => data.to_owned(), @@ -831,16 +777,13 @@ impl Executor { fn commit(&mut self, result: &RawCallResult) { if let Some(state_changeset) = result.state_changeset.as_ref() { - self.db - .commit(state_changeset.clone().into_iter().collect()); + self.db.commit(state_changeset.clone().into_iter().collect()); } } fn inspector(&self) -> InspectorStack { - let mut stack = InspectorStack { - logs: Some(LogCollector::default()), - ..Default::default() - }; + let mut stack = + InspectorStack { logs: Some(LogCollector::default()), ..Default::default() }; if self.debugger { let gas_inspector = Rc::new(RefCell::new(GasInspector::default())); stack.gas = Some(gas_inspector.clone()); @@ -857,10 +800,7 @@ impl Executor { value: U256, ) -> Env { Env { - block: BlockEnv { - gas_limit: self.gas_limit, - ..BlockEnv::default() - }, + block: BlockEnv { gas_limit: self.gas_limit, ..BlockEnv::default() }, tx: TxEnv { caller, transact_to, diff --git a/snark-verifier/src/loader/halo2/loader.rs b/snark-verifier/src/loader/halo2/loader.rs index 31be9841..105972c0 100644 --- a/snark-verifier/src/loader/halo2/loader.rs +++ b/snark-verifier/src/loader/halo2/loader.rs @@ -136,15 +136,15 @@ impl> Halo2Loader { | (Value::Constant(constant), Value::Assigned(assigned)) => { Value::Assigned(self.scalar_chip().sum_with_coeff_and_const( &mut self.ctx_mut(), - &[(C::Scalar::one(), assigned)], + &[(C::Scalar::ONE, assigned)], *constant, )) } (Value::Assigned(lhs), Value::Assigned(rhs)) => { Value::Assigned(self.scalar_chip().sum_with_coeff_and_const( &mut self.ctx_mut(), - &[(C::Scalar::one(), lhs), (C::Scalar::one(), rhs)], - C::Scalar::zero(), + &[(C::Scalar::ONE, lhs), (C::Scalar::ONE, rhs)], + C::Scalar::ZERO, )) } }; @@ -161,14 +161,14 @@ impl> Halo2Loader { (Value::Constant(constant), Value::Assigned(assigned)) => { Value::Assigned(self.scalar_chip().sum_with_coeff_and_const( &mut self.ctx_mut(), - &[(-C::Scalar::one(), assigned)], + &[(-C::Scalar::ONE, assigned)], *constant, )) } (Value::Assigned(assigned), Value::Constant(constant)) => { Value::Assigned(self.scalar_chip().sum_with_coeff_and_const( &mut self.ctx_mut(), - &[(C::Scalar::one(), assigned)], + &[(C::Scalar::ONE, assigned)], -*constant, )) } @@ -191,14 +191,14 @@ impl> Halo2Loader { Value::Assigned(self.scalar_chip().sum_with_coeff_and_const( &mut self.ctx_mut(), &[(*constant, assigned)], - C::Scalar::zero(), + C::Scalar::ZERO, )) } (Value::Assigned(lhs), Value::Assigned(rhs)) => { Value::Assigned(self.scalar_chip().sum_products_with_coeff_and_const( &mut self.ctx_mut(), - &[(C::Scalar::one(), lhs, rhs)], - C::Scalar::zero(), + &[(C::Scalar::ONE, lhs, rhs)], + C::Scalar::ZERO, )) } }; @@ -557,7 +557,7 @@ impl> EcPointLoader for Rc + if scalar.eq(&C::Scalar::ONE) => { variable_base_non_scaled.push(base); } diff --git a/snark-verifier/src/loader/halo2/shim.rs b/snark-verifier/src/loader/halo2/shim.rs index 790c9e22..9d010d2b 100644 --- a/snark-verifier/src/loader/halo2/shim.rs +++ b/snark-verifier/src/loader/halo2/shim.rs @@ -1,8 +1,8 @@ -use crate::util::arithmetic::{CurveAffine, FieldExt}; +use crate::util::arithmetic::{CurveAffine, PrimeField}; use std::{fmt::Debug, ops::Deref}; /// Instructions to handle field element operations. -pub trait IntegerInstructions: Clone + Debug { +pub trait IntegerInstructions: Clone + Debug { /// Context (either enhanced `region` or some kind of builder). type Context: Debug; /// Assigned cell. @@ -24,8 +24,8 @@ pub trait IntegerInstructions: Clone + Debug { fn sum_with_coeff_and_const( &self, ctx: &mut Self::Context, - values: &[(F::Scalar, impl Deref)], - constant: F::Scalar, + values: &[(F, impl Deref)], + constant: F, ) -> Self::AssignedInteger; /// Sum product of integers with coefficients and constant. @@ -33,11 +33,11 @@ pub trait IntegerInstructions: Clone + Debug { &self, ctx: &mut Self::Context, values: &[( - F::Scalar, + F, impl Deref, impl Deref, )], - constant: F::Scalar, + constant: F, ) -> Self::AssignedInteger; /// Returns `lhs - rhs`. @@ -132,25 +132,26 @@ mod halo2_lib { use crate::halo2_proofs::halo2curves::CurveAffineExt; use crate::{ loader::halo2::{EccInstructions, IntegerInstructions}, - util::arithmetic::CurveAffine, + util::arithmetic::{CurveAffine, PrimeField}, }; use halo2_base::{ self, gates::{builder::GateThreadBuilder, GateChip, GateInstructions, RangeInstructions}, + utils::BigPrimeField, AssignedValue, QuantumCell::{Constant, Existing}, }; use halo2_ecc::bigint::ProperCrtUint; use halo2_ecc::{ ecc::{BaseFieldEccChip, EcPoint}, - fields::{FieldChip, PrimeField}, + fields::FieldChip, }; use std::ops::Deref; type AssignedInteger = ProperCrtUint<::ScalarExt>; type AssignedEcPoint = EcPoint<::ScalarExt, AssignedInteger>; - impl IntegerInstructions for GateChip { + impl IntegerInstructions for GateChip { type Context = GateThreadBuilder; type AssignedCell = AssignedValue; type AssignedInteger = AssignedValue; @@ -166,14 +167,14 @@ mod halo2_lib { fn sum_with_coeff_and_const( &self, ctx: &mut Self::Context, - values: &[(F::Scalar, impl Deref)], + values: &[(F, impl Deref)], constant: F, ) -> Self::AssignedInteger { let mut a = Vec::with_capacity(values.len() + 1); let mut b = Vec::with_capacity(values.len() + 1); - if constant != F::zero() { + if constant != F::ZERO { a.push(Constant(constant)); - b.push(Constant(F::one())); + b.push(Constant(F::ONE)); } a.extend(values.iter().map(|(_, a)| Existing(*a.deref()))); b.extend(values.iter().map(|(c, _)| Constant(*c))); @@ -184,7 +185,7 @@ mod halo2_lib { &self, ctx: &mut Self::Context, values: &[( - F::Scalar, + F, impl Deref, impl Deref, )], @@ -220,8 +221,8 @@ mod halo2_lib { ) -> Self::AssignedInteger { // make sure scalar != 0 let is_zero = self.is_zero(ctx.main(0), *a); - self.assert_is_const(ctx.main(0), &is_zero, &F::zero()); - GateInstructions::div_unsafe(self, ctx.main(0), Constant(F::one()), Existing(*a)) + self.assert_is_const(ctx.main(0), &is_zero, &F::ZERO); + GateInstructions::div_unsafe(self, ctx.main(0), Constant(F::ONE), Existing(*a)) } fn assert_equal( @@ -236,8 +237,8 @@ mod halo2_lib { impl<'chip, C: CurveAffineExt> EccInstructions for BaseFieldEccChip<'chip, C> where - C::ScalarExt: PrimeField, - C::Base: PrimeField, + C::ScalarExt: BigPrimeField, + C::Base: BigPrimeField, { type Context = GateThreadBuilder; type ScalarChip = GateChip; diff --git a/snark-verifier/src/pcs/ipa.rs b/snark-verifier/src/pcs/ipa.rs index 6358e15d..288745d7 100644 --- a/snark-verifier/src/pcs/ipa.rs +++ b/snark-verifier/src/pcs/ipa.rs @@ -379,7 +379,7 @@ fn h_eval>(xi: &[T], z: &T) -> T { fn h_coeffs(xi: &[F], scalar: F) -> Vec { assert!(!xi.is_empty()); - let mut coeffs = vec![F::zero(); 1 << xi.len()]; + let mut coeffs = vec![F::ZERO; 1 << xi.len()]; coeffs[0] = scalar; for (len, xi) in xi.iter().rev().enumerate().map(|(i, xi)| (1 << i, xi)) { diff --git a/snark-verifier/src/pcs/ipa/accumulation.rs b/snark-verifier/src/pcs/ipa/accumulation.rs index 56d61aa7..51434541 100644 --- a/snark-verifier/src/pcs/ipa/accumulation.rs +++ b/snark-verifier/src/pcs/ipa/accumulation.rs @@ -186,13 +186,13 @@ where let (u, h) = instances .iter() - .map(|IpaAccumulator { u, xi }| (*u, h_coeffs(xi, C::Scalar::one()))) + .map(|IpaAccumulator { u, xi }| (*u, h_coeffs(xi, C::Scalar::ONE))) .chain(a_b_u.map(|(a, b, u)| { ( u, iter::empty() .chain([b, a]) - .chain(iter::repeat_with(C::Scalar::zero).take(pk.domain.n - 2)) + .chain(iter::repeat(C::Scalar::ZERO).take(pk.domain.n - 2)) .collect(), ) })) diff --git a/snark-verifier/src/pcs/ipa/decider.rs b/snark-verifier/src/pcs/ipa/decider.rs index 5235a857..6fd7026b 100644 --- a/snark-verifier/src/pcs/ipa/decider.rs +++ b/snark-verifier/src/pcs/ipa/decider.rs @@ -48,7 +48,7 @@ mod native { dk: &Self::DecidingKey, IpaAccumulator { u, xi }: IpaAccumulator, ) -> Result<(), Error> { - let h = h_coeffs(&xi, C::Scalar::one()); + let h = h_coeffs(&xi, C::Scalar::ONE); (u == multi_scalar_multiplication(&h, &dk.g).to_affine()) .then_some(()) .ok_or_else(|| Error::AssertionFailure("U == commit(G, h)".to_string())) diff --git a/snark-verifier/src/pcs/ipa/multiopen/bgh19.rs b/snark-verifier/src/pcs/ipa/multiopen/bgh19.rs index cae77a5f..538aa4fb 100644 --- a/snark-verifier/src/pcs/ipa/multiopen/bgh19.rs +++ b/snark-verifier/src/pcs/ipa/multiopen/bgh19.rs @@ -5,7 +5,7 @@ use crate::{ PolynomialCommitmentScheme, Query, }, util::{ - arithmetic::{CurveAffine, FieldExt, Fraction}, + arithmetic::{CurveAffine, Fraction, PrimeField}, msm::Msm, transcript::TranscriptRead, Itertools, @@ -159,7 +159,7 @@ where fn query_sets(queries: &[Query]) -> Vec> where - F: FieldExt, + F: PrimeField + Ord, T: Clone, { let poly_shifts = @@ -203,7 +203,7 @@ where fn query_set_coeffs(sets: &[QuerySet], x: &T, x_3: &T) -> Vec> where - F: FieldExt, + F: PrimeField + Ord, T: LoadedScalar, { let loader = x.loader(); @@ -236,7 +236,7 @@ struct QuerySet<'a, F, T> { impl<'a, F, T> QuerySet<'a, F, T> where - F: FieldExt, + F: PrimeField, T: LoadedScalar, { fn msm>( @@ -288,7 +288,7 @@ struct QuerySetCoeff { impl QuerySetCoeff where - F: FieldExt, + F: PrimeField + Ord, T: LoadedScalar, { fn new(shifts: &[F], powers_of_x: &[T], x_3: &T, x_3_minus_x_shift_i: &BTreeMap) -> Self { @@ -303,7 +303,7 @@ where .filter(|&(i, _)| i != j) .map(|(_, shift_i)| (*shift_j - shift_i)) .reduce(|acc, value| acc * value) - .unwrap_or_else(|| F::one()) + .unwrap_or(F::ONE) }) .collect_vec(); diff --git a/snark-verifier/src/pcs/kzg.rs b/snark-verifier/src/pcs/kzg.rs index 8f416ee3..387a108c 100644 --- a/snark-verifier/src/pcs/kzg.rs +++ b/snark-verifier/src/pcs/kzg.rs @@ -18,7 +18,7 @@ pub use accumulator::LimbsEncodingInstructions; /// KZG succinct verifying key. #[derive(Clone, Copy, Debug)] -pub struct KzgSuccinctVerifyingKey { +pub struct KzgSuccinctVerifyingKey { /// Generator. pub g: C, } diff --git a/snark-verifier/src/pcs/kzg/accumulation.rs b/snark-verifier/src/pcs/kzg/accumulation.rs index 1f901568..d71e366e 100644 --- a/snark-verifier/src/pcs/kzg/accumulation.rs +++ b/snark-verifier/src/pcs/kzg/accumulation.rs @@ -19,6 +19,7 @@ pub struct KzgAs(PhantomData<(M, MOS)>); impl AccumulationScheme for KzgAs where M: MultiMillerLoop, + M::G1Affine: CurveAffine, L: Loader, MOS: Clone + Debug, { @@ -139,6 +140,7 @@ where impl AccumulationSchemeProver for KzgAs where M: MultiMillerLoop, + M::G1Affine: CurveAffine, MOS: Clone + Debug, { type ProvingKey = KzgAsProvingKey; @@ -163,7 +165,7 @@ where let blind = pk .zk() .then(|| { - let s = M::Scalar::random(rng); + let s = M::Fr::random(rng); let (g, s_g) = pk.0.unwrap(); let lhs = (s_g * s).to_affine(); let rhs = (g * s).to_affine(); diff --git a/snark-verifier/src/pcs/kzg/accumulator.rs b/snark-verifier/src/pcs/kzg/accumulator.rs index 82d1454b..423ae7d5 100644 --- a/snark-verifier/src/pcs/kzg/accumulator.rs +++ b/snark-verifier/src/pcs/kzg/accumulator.rs @@ -59,7 +59,6 @@ mod native { let [lhs_x, lhs_y, rhs_x, rhs_y]: [_; 4] = limbs .chunks(LIMBS) - .into_iter() .map(|limbs| { fe_from_limbs::<_, _, LIMBS, BITS>( limbs.iter().map(|limb| **limb).collect_vec().try_into().unwrap(), @@ -109,7 +108,6 @@ mod evm { let [lhs_x, lhs_y, rhs_x, rhs_y]: [[_; LIMBS]; 4] = limbs .chunks(LIMBS) - .into_iter() .map(|limbs| limbs.to_vec().try_into().unwrap()) .collect_vec() .try_into() @@ -204,14 +202,15 @@ mod halo2 { mod halo2_lib { use super::*; use halo2_base::halo2_proofs::halo2curves::CurveAffineExt; - use halo2_ecc::{ecc::BaseFieldEccChip, fields::PrimeField}; + use halo2_base::utils::BigPrimeField; + use halo2_ecc::ecc::BaseFieldEccChip; impl<'chip, C, const LIMBS: usize, const BITS: usize> LimbsEncodingInstructions for BaseFieldEccChip<'chip, C> where C: CurveAffineExt, - C::ScalarExt: PrimeField, - C::Base: PrimeField, + C::ScalarExt: BigPrimeField, + C::Base: BigPrimeField, { fn assign_ec_point_from_limbs( &self, diff --git a/snark-verifier/src/pcs/kzg/decider.rs b/snark-verifier/src/pcs/kzg/decider.rs index 59f1afbf..04f2caaf 100644 --- a/snark-verifier/src/pcs/kzg/decider.rs +++ b/snark-verifier/src/pcs/kzg/decider.rs @@ -1,4 +1,7 @@ -use crate::{pcs::kzg::KzgSuccinctVerifyingKey, util::arithmetic::MultiMillerLoop}; +use crate::{ + pcs::kzg::KzgSuccinctVerifyingKey, + util::arithmetic::{CurveAffine, MultiMillerLoop}, +}; use std::marker::PhantomData; /// KZG deciding key. @@ -23,7 +26,10 @@ impl KzgDecidingKey { } } -impl From<(M::G1Affine, M::G2Affine, M::G2Affine)> for KzgDecidingKey { +impl From<(M::G1Affine, M::G2Affine, M::G2Affine)> for KzgDecidingKey +where + M::G1Affine: CurveAffine, +{ fn from((g1, g2, s_g2): (M::G1Affine, M::G2Affine, M::G2Affine)) -> KzgDecidingKey { KzgDecidingKey::new(g1, g2, s_g2) } @@ -43,7 +49,7 @@ mod native { AccumulationDecider, }, util::{ - arithmetic::{Group, MillerLoopResult, MultiMillerLoop}, + arithmetic::{CurveAffine, Group, MillerLoopResult, MultiMillerLoop}, Itertools, }, Error, @@ -53,6 +59,7 @@ mod native { impl AccumulationDecider for KzgAs where M: MultiMillerLoop, + M::G1Affine: CurveAffine, MOS: Clone + Debug, { type DecidingKey = KzgDecidingKey; @@ -103,7 +110,9 @@ mod evm { impl AccumulationDecider> for KzgAs where M: MultiMillerLoop, - M::Scalar: PrimeField, + M::G1Affine: CurveAffine, + M::G2Affine: CurveAffine, + M::Fr: PrimeField, MOS: Clone + Debug, { type DecidingKey = KzgDecidingKey; @@ -152,7 +161,7 @@ mod evm { loader.code_mut().runtime_append(code); let challenge = loader.scalar(Value::Memory(challenge_ptr)); - let powers_of_challenge = LoadedScalar::::powers(&challenge, lhs.len()); + let powers_of_challenge = LoadedScalar::::powers(&challenge, lhs.len()); let [lhs, rhs] = [lhs, rhs].map(|msms| { msms.iter() .zip(powers_of_challenge.iter()) diff --git a/snark-verifier/src/pcs/kzg/multiopen/bdfg21.rs b/snark-verifier/src/pcs/kzg/multiopen/bdfg21.rs index 3a448056..d1398ebb 100644 --- a/snark-verifier/src/pcs/kzg/multiopen/bdfg21.rs +++ b/snark-verifier/src/pcs/kzg/multiopen/bdfg21.rs @@ -6,7 +6,7 @@ use crate::{ PolynomialCommitmentScheme, Query, }, util::{ - arithmetic::{CurveAffine, FieldExt, Fraction, MultiMillerLoop}, + arithmetic::{CurveAffine, Fraction, MultiMillerLoop, PrimeField}, msm::Msm, transcript::TranscriptRead, Itertools, @@ -27,6 +27,8 @@ pub struct Bdfg21; impl PolynomialCommitmentScheme for KzgAs where M: MultiMillerLoop, + M::G1Affine: CurveAffine, + M::Fr: Ord, L: Loader, { type VerifyingKey = KzgSuccinctVerifyingKey; @@ -35,7 +37,7 @@ where fn read_proof( _: &KzgSuccinctVerifyingKey, - _: &[Query], + _: &[Query], transcript: &mut T, ) -> Result, Error> where @@ -48,22 +50,21 @@ where svk: &KzgSuccinctVerifyingKey, commitments: &[Msm], z: &L::LoadedScalar, - queries: &[Query], + queries: &[Query], proof: &Bdfg21Proof, ) -> Result { let sets = query_sets(queries); let f = { let coeffs = query_set_coeffs(&sets, z, &proof.z_prime); - let powers_of_mu = proof - .mu - .powers(sets.iter().map(|set| set.polys.len()).max().unwrap()); + let powers_of_mu = + proof.mu.powers(sets.iter().map(|set| set.polys.len()).max().unwrap()); let msms = sets .iter() .zip(coeffs.iter()) .map(|(set, coeff)| set.msm(coeff, commitments, &powers_of_mu)); - msms.zip(proof.gamma.powers(sets.len()).into_iter()) + msms.zip(proof.gamma.powers(sets.len())) .map(|(msm, power_of_gamma)| msm * &power_of_gamma) .sum::>() - Msm::base(&proof.w) * &coeffs[0].z_s @@ -72,10 +73,7 @@ where let rhs = Msm::base(&proof.w_prime); let lhs = f + rhs.clone() * &proof.z_prime; - Ok(KzgAccumulator::new( - lhs.evaluate(Some(svk.g)), - rhs.evaluate(Some(svk.g)), - )) + Ok(KzgAccumulator::new(lhs.evaluate(Some(svk.g)), rhs.evaluate(Some(svk.g)))) } } @@ -104,24 +102,14 @@ where let w = transcript.read_ec_point()?; let z_prime = transcript.squeeze_challenge(); let w_prime = transcript.read_ec_point()?; - Ok(Bdfg21Proof { - mu, - gamma, - w, - z_prime, - w_prime, - }) + Ok(Bdfg21Proof { mu, gamma, w, z_prime, w_prime }) } } -fn query_sets(queries: &[Query]) -> Vec> { - let poly_shifts = queries.iter().fold( - Vec::<(usize, Vec, Vec<&T>)>::new(), - |mut poly_shifts, query| { - if let Some(pos) = poly_shifts - .iter() - .position(|(poly, _, _)| *poly == query.poly) - { +fn query_sets(queries: &[Query]) -> Vec> { + let poly_shifts = + queries.iter().fold(Vec::<(usize, Vec, Vec<&T>)>::new(), |mut poly_shifts, query| { + if let Some(pos) = poly_shifts.iter().position(|(poly, _, _)| *poly == query.poly) { let (_, shifts, evals) = &mut poly_shifts[pos]; if !shifts.contains(&query.shift) { shifts.push(query.shift); @@ -131,67 +119,47 @@ fn query_sets(queries: &[Query]) -> Vec>::new(), - |mut sets, (poly, shifts, evals)| { - if let Some(pos) = sets.iter().position(|set| { - BTreeSet::from_iter(set.shifts.iter()) == BTreeSet::from_iter(shifts.iter()) - }) { - let set = &mut sets[pos]; - if !set.polys.contains(&poly) { - set.polys.push(poly); - set.evals.push( - set.shifts - .iter() - .map(|lhs| { - let idx = shifts.iter().position(|rhs| lhs == rhs).unwrap(); - evals[idx] - }) - .collect(), - ); - } - } else { - let set = QuerySet { - shifts, - polys: vec![poly], - evals: vec![evals], - }; - sets.push(set); + }); + + poly_shifts.into_iter().fold(Vec::>::new(), |mut sets, (poly, shifts, evals)| { + if let Some(pos) = sets.iter().position(|set| { + BTreeSet::from_iter(set.shifts.iter()) == BTreeSet::from_iter(shifts.iter()) + }) { + let set = &mut sets[pos]; + if !set.polys.contains(&poly) { + set.polys.push(poly); + set.evals.push( + set.shifts + .iter() + .map(|lhs| { + let idx = shifts.iter().position(|rhs| lhs == rhs).unwrap(); + evals[idx] + }) + .collect(), + ); } - sets - }, - ) + } else { + let set = QuerySet { shifts, polys: vec![poly], evals: vec![evals] }; + sets.push(set); + } + sets + }) } -fn query_set_coeffs<'a, F: FieldExt, T: LoadedScalar>( - sets: &[QuerySet<'a, F, T>], +fn query_set_coeffs>( + sets: &[QuerySet], z: &T, z_prime: &T, ) -> Vec> { let loader = z.loader(); - let superset = sets - .iter() - .flat_map(|set| set.shifts.clone()) - .sorted() - .dedup(); + let superset = sets.iter().flat_map(|set| set.shifts.clone()).sorted().dedup(); - let size = sets - .iter() - .map(|set| set.shifts.len()) - .chain(Some(2)) - .max() - .unwrap(); + let size = sets.iter().map(|set| set.shifts.len()).chain(Some(2)).max().unwrap(); let powers_of_z = z.powers(size); - let z_prime_minus_z_shift_i = BTreeMap::from_iter(superset.map(|shift| { - ( - shift, - z_prime.clone() - z.clone() * loader.load_const(&shift), - ) - })); + let z_prime_minus_z_shift_i = BTreeMap::from_iter( + superset.map(|shift| (shift, z_prime.clone() - z.clone() * loader.load_const(&shift))), + ); let mut z_s_1 = None; let mut coeffs = sets @@ -225,7 +193,7 @@ struct QuerySet<'a, F, T> { evals: Vec>, } -impl<'a, F: FieldExt, T: LoadedScalar> QuerySet<'a, F, T> { +impl<'a, F: PrimeField, T: LoadedScalar> QuerySet<'a, F, T> { fn msm>( &self, coeff: &QuerySetCoeff, @@ -270,7 +238,7 @@ struct QuerySetCoeff { impl QuerySetCoeff where - F: FieldExt, + F: PrimeField + Ord, T: LoadedScalar, { fn new( @@ -292,7 +260,7 @@ where .filter(|&(i, _)| i != j) .map(|(_, shift_i)| (*shift_j - shift_i)) .reduce(|acc, value| acc * value) - .unwrap_or_else(|| F::one()) + .unwrap_or(F::ONE) }) .collect_vec(); @@ -312,10 +280,7 @@ where .collect_vec(); let z_s = loader.product( - &shifts - .iter() - .map(|shift| z_prime_minus_z_shift_i.get(shift).unwrap()) - .collect_vec(), + &shifts.iter().map(|shift| z_prime_minus_z_shift_i.get(shift).unwrap()).collect_vec(), ); let z_s_1_over_z_s = z_s_1.clone().map(|z_s_1| Fraction::new(z_s_1, z_s.clone())); @@ -344,13 +309,8 @@ where .iter_mut() .chain(self.commitment_coeff.as_mut()) .for_each(Fraction::evaluate); - let barycentric_weights_sum = loader.sum( - &self - .eval_coeffs - .iter() - .map(Fraction::evaluated) - .collect_vec(), - ); + let barycentric_weights_sum = + loader.sum(&self.eval_coeffs.iter().map(Fraction::evaluated).collect_vec()); self.r_eval_coeff = Some(match self.commitment_coeff.as_ref() { Some(coeff) => Fraction::new(coeff.evaluated().clone(), barycentric_weights_sum), None => Fraction::one_over(barycentric_weights_sum), @@ -370,13 +330,9 @@ impl CostEstimation for KzgAs where M: MultiMillerLoop, { - type Input = Vec>; + type Input = Vec>; - fn estimate_cost(_: &Vec>) -> Cost { - Cost { - num_commitment: 2, - num_msm: 2, - ..Default::default() - } + fn estimate_cost(_: &Vec>) -> Cost { + Cost { num_commitment: 2, num_msm: 2, ..Default::default() } } } diff --git a/snark-verifier/src/pcs/kzg/multiopen/gwc19.rs b/snark-verifier/src/pcs/kzg/multiopen/gwc19.rs index e5741163..da5d51a6 100644 --- a/snark-verifier/src/pcs/kzg/multiopen/gwc19.rs +++ b/snark-verifier/src/pcs/kzg/multiopen/gwc19.rs @@ -23,6 +23,7 @@ pub struct Gwc19; impl PolynomialCommitmentScheme for KzgAs where M: MultiMillerLoop, + M::G1Affine: CurveAffine, L: Loader, { type VerifyingKey = KzgSuccinctVerifyingKey; @@ -31,7 +32,7 @@ where fn read_proof( _: &Self::VerifyingKey, - queries: &[Query], + queries: &[Query], transcript: &mut T, ) -> Result where @@ -44,15 +45,13 @@ where svk: &Self::VerifyingKey, commitments: &[Msm], z: &L::LoadedScalar, - queries: &[Query], + queries: &[Query], proof: &Self::Proof, ) -> Result { let sets = query_sets(queries); let powers_of_u = &proof.u.powers(sets.len()); let f = { - let powers_of_v = proof - .v - .powers(sets.iter().map(|set| set.polys.len()).max().unwrap()); + let powers_of_v = proof.v.powers(sets.iter().map(|set| set.polys.len()).max().unwrap()); sets.iter() .map(|set| set.msm(commitments, &powers_of_v)) .zip(powers_of_u.iter()) @@ -67,11 +66,7 @@ where .zip(powers_of_u.iter()) .map(|(w, power_of_u)| Msm::base(w) * power_of_u) .collect_vec(); - let lhs = f + rhs - .iter() - .zip(z_omegas) - .map(|(uw, z_omega)| uw.clone() * &z_omega) - .sum(); + let lhs = f + rhs.iter().zip(z_omegas).map(|(uw, z_omega)| uw.clone() * &z_omega).sum(); Ok(KzgAccumulator::new( lhs.evaluate(Some(svk.g)), @@ -161,14 +156,10 @@ impl CostEstimation for KzgAs where M: MultiMillerLoop, { - type Input = Vec>; + type Input = Vec>; - fn estimate_cost(queries: &Vec>) -> Cost { + fn estimate_cost(queries: &Vec>) -> Cost { let num_w = query_sets(queries).len(); - Cost { - num_commitment: num_w, - num_msm: num_w, - ..Default::default() - } + Cost { num_commitment: num_w, num_msm: num_w, ..Default::default() } } } diff --git a/snark-verifier/src/system/halo2.rs b/snark-verifier/src/system/halo2.rs index 98f4488c..2dc5751d 100644 --- a/snark-verifier/src/system/halo2.rs +++ b/snark-verifier/src/system/halo2.rs @@ -7,7 +7,7 @@ use crate::halo2_proofs::{ }; use crate::{ util::{ - arithmetic::{root_of_unity, CurveAffine, Domain, FieldExt, Rotation}, + arithmetic::{root_of_unity, CurveAffine, Domain, PrimeField, Rotation}, Itertools, }, verifier::plonk::protocol::{ @@ -161,7 +161,7 @@ impl From for Rotation { } } -struct Polynomials<'a, F: FieldExt> { +struct Polynomials<'a, F: PrimeField> { cs: &'a ConstraintSystem, zk: bool, query_instance: bool, @@ -179,7 +179,7 @@ struct Polynomials<'a, F: FieldExt> { num_lookup_z: usize, } -impl<'a, F: FieldExt> Polynomials<'a, F> { +impl<'a, F: PrimeField> Polynomials<'a, F> { fn new( cs: &'a ConstraintSystem, zk: bool, @@ -474,7 +474,7 @@ impl<'a, F: FieldExt> Polynomials<'a, F> { } fn l_active(&self) -> Expression { - Expression::Constant(F::one()) - self.l_last() - self.l_blind() + Expression::Constant(F::ONE) - self.l_last() - self.l_blind() } fn system_challenge_offset(&self) -> usize { @@ -499,7 +499,7 @@ impl<'a, F: FieldExt> Polynomials<'a, F> { } fn permutation_constraints(&'a self, t: usize) -> impl IntoIterator> + 'a { - let one = &Expression::Constant(F::one()); + let one = &Expression::Constant(F::ONE); let l_0 = &Expression::::CommonPolynomial(CommonPolynomial::Lagrange(0)); let l_last = &self.l_last(); let l_active = &self.l_active(); @@ -591,7 +591,7 @@ impl<'a, F: FieldExt> Polynomials<'a, F> { } fn lookup_constraints(&'a self, t: usize) -> impl IntoIterator> + 'a { - let one = &Expression::Constant(F::one()); + let one = &Expression::Constant(F::ONE); let l_0 = &Expression::::CommonPolynomial(CommonPolynomial::Lagrange(0)); let l_last = &self.l_last(); let l_active = &self.l_active(); @@ -698,7 +698,7 @@ impl EncodedChallenge for MockChallenge { } #[derive(Default)] -struct MockTranscript(F); +struct MockTranscript(F); impl Transcript for MockTranscript { fn squeeze_challenge(&mut self) -> MockChallenge { diff --git a/snark-verifier/src/system/halo2/transcript.rs b/snark-verifier/src/system/halo2/transcript.rs index 9cfd6b89..10da3a22 100644 --- a/snark-verifier/src/system/halo2/transcript.rs +++ b/snark-verifier/src/system/halo2/transcript.rs @@ -1,7 +1,6 @@ //! Transcripts implemented with both `halo2_proofs::transcript` and //! `crate::util::transcript`. use crate::halo2_proofs; -use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite, Challenge255}; use crate::{ loader::native::{self, NativeLoader}, util::{ @@ -10,6 +9,8 @@ use crate::{ }, Error, }; +use halo2_proofs::transcript::{Blake2bRead, Blake2bWrite, Challenge255}; +use pairing::group::ff::FromUniformBytes; use std::io::{Read, Write}; #[cfg(feature = "loader_evm")] @@ -18,7 +19,10 @@ pub mod evm; #[cfg(feature = "loader_halo2")] pub mod halo2; -impl Transcript for Blake2bRead> { +impl Transcript for Blake2bRead> +where + C::Scalar: FromUniformBytes<64>, +{ fn loader(&self) -> &NativeLoader { &native::LOADER } @@ -38,8 +42,9 @@ impl Transcript for Blake2bRead TranscriptRead - for Blake2bRead> +impl TranscriptRead for Blake2bRead> +where + C::Scalar: FromUniformBytes<64>, { fn read_scalar(&mut self) -> Result { halo2_proofs::transcript::TranscriptRead::read_scalar(self) @@ -52,7 +57,10 @@ impl TranscriptRead } } -impl Transcript for Blake2bWrite> { +impl Transcript for Blake2bWrite> +where + C::Scalar: FromUniformBytes<64>, +{ fn loader(&self) -> &NativeLoader { &native::LOADER } @@ -72,7 +80,10 @@ impl Transcript for Blake2bWrite TranscriptWrite for Blake2bWrite, C, Challenge255> { +impl TranscriptWrite for Blake2bWrite, C, Challenge255> +where + C::Scalar: FromUniformBytes<64>, +{ fn write_scalar(&mut self, scalar: C::Scalar) -> Result<(), Error> { halo2_proofs::transcript::TranscriptWrite::write_scalar(self, scalar) .map_err(|err| Error::Transcript(err.kind(), err.to_string())) diff --git a/snark-verifier/src/system/halo2/transcript/halo2.rs b/snark-verifier/src/system/halo2/transcript/halo2.rs index 86b1929c..8a0ce6d4 100644 --- a/snark-verifier/src/system/halo2/transcript/halo2.rs +++ b/snark-verifier/src/system/halo2/transcript/halo2.rs @@ -1,6 +1,7 @@ //! Transcript for verifier in [`halo2_proofs`] circuit. use crate::halo2_proofs; +use crate::util::arithmetic::FieldExt; use crate::{ loader::{ halo2::{EcPoint, EccInstructions, Halo2Loader, Scalar}, @@ -64,7 +65,10 @@ where { /// Initialize [`PoseidonTranscript`] given readable or writeable stream for /// verifying or proving with [`NativeLoader`]. - pub fn new(loader: &Rc>, stream: R) -> Self { + pub fn new(loader: &Rc>, stream: R) -> Self + where + C::Scalar: FieldExt, + { let buf = Poseidon::new::(loader); Self { loader: loader.clone(), stream, buf } } @@ -165,7 +169,10 @@ impl(stream: S) -> Self { + pub fn new(stream: S) -> Self + where + C::Scalar: FieldExt, + { Self { loader: NativeLoader, stream, @@ -375,6 +382,7 @@ impl where C: CurveAffine, + C::Scalar: FieldExt, R: Read, { fn init(reader: R) -> Self { @@ -409,6 +417,7 @@ impl where C: CurveAffine, + C::Scalar: FieldExt, W: Write, { fn init(writer: W) -> Self { @@ -423,12 +432,13 @@ where mod halo2_lib { use crate::halo2_curves::CurveAffineExt; use crate::system::halo2::transcript::halo2::NativeEncoding; - use halo2_ecc::{ecc::BaseFieldEccChip, fields::PrimeField}; + use halo2_base::utils::BigPrimeField; + use halo2_ecc::ecc::BaseFieldEccChip; impl<'chip, C: CurveAffineExt> NativeEncoding for BaseFieldEccChip<'chip, C> where - C::Scalar: PrimeField, - C::Base: PrimeField, + C::Scalar: BigPrimeField, + C::Base: BigPrimeField, { fn encode( &self, diff --git a/snark-verifier/src/util/arithmetic.rs b/snark-verifier/src/util/arithmetic.rs index 97962e32..070277a5 100644 --- a/snark-verifier/src/util/arithmetic.rs +++ b/snark-verifier/src/util/arithmetic.rs @@ -4,15 +4,15 @@ use crate::halo2_curves; use crate::util::Itertools; pub use halo2_curves::{ group::{ - ff::{BatchInvert, Field, PrimeField}, + ff::{BatchInvert, Field, FromUniformBytes, PrimeField}, prime::PrimeCurveAffine, Curve, Group, GroupEncoding, }, - pairing::MillerLoopResult, - Coordinates, CurveAffine, CurveExt, FieldExt, + Coordinates, CurveAffine, CurveExt, }; use num_bigint::BigUint; use num_traits::One; +pub use pairing::MillerLoopResult; use serde::{Deserialize, Serialize}; use std::{ cmp::Ordering, @@ -22,9 +22,14 @@ use std::{ }; /// [`halo2_curves::pairing::MultiMillerLoop`] with [`std::fmt::Debug`]. -pub trait MultiMillerLoop: halo2_curves::pairing::MultiMillerLoop + Debug {} +pub trait MultiMillerLoop: pairing::MultiMillerLoop + Debug {} -impl MultiMillerLoop for M {} +impl MultiMillerLoop for M {} + +/// Trait for fields that can implement Poseidon hash +pub trait FieldExt: PrimeField + FromUniformBytes<64> + Ord {} + +impl + Ord> FieldExt for F {} /// Operations that could be done with field elements. pub trait FieldOps: @@ -54,7 +59,7 @@ pub fn batch_invert_and_mul(values: &mut [F], coeff: &F) { } let products = values .iter() - .scan(F::one(), |acc, value| { + .scan(F::ONE, |acc, value| { *acc *= value; Some(*acc) }) @@ -65,7 +70,7 @@ pub fn batch_invert_and_mul(values: &mut [F], coeff: &F) { * coeff; for (value, product) in - values.iter_mut().rev().zip(products.into_iter().rev().skip(1).chain(Some(F::one()))) + values.iter_mut().rev().zip(products.into_iter().rev().skip(1).chain(Some(F::ONE))) { let mut inv = all_product_inv * product; mem::swap(value, &mut inv); @@ -75,7 +80,7 @@ pub fn batch_invert_and_mul(values: &mut [F], coeff: &F) { /// Batch invert [`PrimeField`] elements. pub fn batch_invert(values: &mut [F]) { - batch_invert_and_mul(values, &F::one()) + batch_invert_and_mul(values, &F::ONE) } /// Root of unity of 2^k-sized multiplicative subgroup of [`PrimeField`] by @@ -88,7 +93,7 @@ pub fn batch_invert(values: &mut [F]) { pub fn root_of_unity(k: usize) -> F { assert!(k <= F::S as usize); - iter::successors(Some(F::root_of_unity()), |acc| Some(acc.square())) + iter::successors(Some(F::ROOT_OF_UNITY), |acc| Some(acc.square())) .take(F::S as usize - k + 1) .last() .unwrap() @@ -230,7 +235,7 @@ impl Fraction { /// Modulus of a [`PrimeField`] pub fn modulus() -> BigUint { - fe_to_big(-F::one()) + 1usize + fe_to_big(-F::ONE) + 1usize } /// Convert a [`BigUint`] into a [`PrimeField`] . @@ -286,7 +291,7 @@ pub fn fe_to_limbs(scalar: F) -> impl Iterator { - iter::successors(Some(F::one()), move |power| Some(scalar * power)) + iter::successors(Some(F::ONE), move |power| Some(scalar * power)) } /// Compute inner product of 2 slice of [`Field`]. diff --git a/snark-verifier/src/util/hash/poseidon.rs b/snark-verifier/src/util/hash/poseidon.rs index 1ff06ab9..e826ac52 100644 --- a/snark-verifier/src/util/hash/poseidon.rs +++ b/snark-verifier/src/util/hash/poseidon.rs @@ -1,9 +1,12 @@ #![allow(clippy::needless_range_loop)] // for clarity of matrix operations use crate::{ loader::{LoadedScalar, ScalarLoader}, - util::{arithmetic::FieldExt, Itertools}, + util::{ + arithmetic::{FieldExt, PrimeField}, + Itertools, + }, }; -use poseidon_circuit::poseidon::primitives::Spec as PoseidonSpec; // trait +use poseidon_rs::poseidon::primitives::Spec as PoseidonSpec; // trait use std::{iter, marker::PhantomData, mem}; #[cfg(test)] @@ -12,7 +15,7 @@ mod tests; // struct so we can use PoseidonSpec trait to generate round constants and MDS matrix #[derive(Debug)] pub struct Poseidon128Pow5Gen< - F: FieldExt, + F: PrimeField, const T: usize, const RATE: usize, const R_F: usize, @@ -23,7 +26,7 @@ pub struct Poseidon128Pow5Gen< } impl< - F: FieldExt, + F: PrimeField, const T: usize, const RATE: usize, const R_F: usize, @@ -57,7 +60,7 @@ impl< /// `OptimizedPoseidonSpec` holds construction parameters as well as constants that are used in /// permutation step. #[derive(Debug, Clone)] -pub struct OptimizedPoseidonSpec { +pub struct OptimizedPoseidonSpec { pub(crate) r_f: usize, pub(crate) mds_matrices: MDSMatrices, pub(crate) constants: OptimizedConstants, @@ -67,7 +70,7 @@ pub struct OptimizedPoseidonSpec /// full rounds has T sized constants there is a single constant for each /// partial round #[derive(Debug, Clone)] -pub struct OptimizedConstants { +pub struct OptimizedConstants { pub(crate) start: Vec<[F; T]>, pub(crate) partial: Vec, pub(crate) end: Vec<[F; T]>, @@ -80,7 +83,7 @@ pub(crate) type Mds = [[F; T]; T]; /// also called `pre_sparse_mds` and sparse matrices that enables us to reduce /// number of multiplications in apply MDS step #[derive(Debug, Clone)] -pub struct MDSMatrices { +pub struct MDSMatrices { pub(crate) mds: MDSMatrix, pub(crate) pre_sparse_mds: MDSMatrix, pub(crate) sparse_matrices: Vec>, @@ -89,18 +92,18 @@ pub struct MDSMatrices { /// `SparseMDSMatrix` are in `[row], [hat | identity]` form and used in linear /// layer of partial rounds instead of the original MDS #[derive(Debug, Clone)] -pub struct SparseMDSMatrix { +pub struct SparseMDSMatrix { pub(crate) row: [F; T], pub(crate) col_hat: [F; RATE], } /// `MDSMatrix` is applied to `State` to achive linear layer of Poseidon #[derive(Clone, Debug)] -pub struct MDSMatrix(pub(crate) Mds); +pub struct MDSMatrix(pub(crate) Mds); -impl MDSMatrix { +impl MDSMatrix { pub(crate) fn mul_vector(&self, v: &[F; T]) -> [F; T] { - let mut res = [F::zero(); T]; + let mut res = [F::ZERO; T]; for i in 0..T { for j in 0..T { res[i] += self.0[i][j] * v[j]; @@ -110,16 +113,16 @@ impl MDSMatrix { } fn identity() -> Mds { - let mut mds = [[F::zero(); T]; T]; + let mut mds = [[F::ZERO; T]; T]; for i in 0..T { - mds[i][i] = F::one(); + mds[i][i] = F::ONE; } mds } /// Multiplies two MDS matrices. Used in sparse matrix calculations fn mul(&self, other: &Self) -> Self { - let mut res = [[F::zero(); T]; T]; + let mut res = [[F::ZERO; T]; T]; for i in 0..T { for j in 0..T { for k in 0..T { @@ -131,7 +134,7 @@ impl MDSMatrix { } fn transpose(&self) -> Self { - let mut res = [[F::zero(); T]; T]; + let mut res = [[F::ZERO; T]; T]; for i in 0..T { for j in 0..T { res[i][j] = self.0[j][i]; @@ -141,11 +144,11 @@ impl MDSMatrix { } fn determinant(m: [[F; N]; N]) -> F { - let mut res = F::one(); + let mut res = F::ONE; let mut m = m; for i in 0..N { let mut pivot = i; - while m[pivot][i] == F::zero() { + while m[pivot][i] == F::ZERO { pivot += 1; assert!(pivot < N, "matrix is not invertible"); } @@ -196,7 +199,7 @@ impl MDSMatrix { let w = self.0.iter().skip(1).map(|row| row[0]).collect::>(); // m_hat is the `(t-1 * t-1)` right bottom sub-matrix of m := self.0 - let mut m_hat = [[F::zero(); RATE]; RATE]; + let mut m_hat = [[F::ZERO; RATE]; RATE]; for i in 0..RATE { for j in 0..RATE { m_hat[i][j] = self.0[i + 1][j + 1]; @@ -204,7 +207,7 @@ impl MDSMatrix { } // w_hat = m_hat^{-1} * w, where m_hat^{-1} is matrix inverse and * is matrix mult // we avoid computing m_hat^{-1} explicitly by using Cramer's rule: https://en.wikipedia.org/wiki/Cramer%27s_rule - let mut w_hat = [F::zero(); RATE]; + let mut w_hat = [F::ZERO; RATE]; let det = Self::determinant(m_hat); let det_inv = Option::::from(det.invert()).expect("matrix is not invertible"); for j in 0..RATE { @@ -225,9 +228,12 @@ impl MDSMatrix { } } -impl OptimizedPoseidonSpec { +impl OptimizedPoseidonSpec { /// Generate new spec with specific number of full and partial rounds. `SECURE_MDS` is usually 0, but may need to be specified because insecure matrices may sometimes be generated - pub fn new() -> Self { + pub fn new() -> Self + where + F: FieldExt, + { let (round_constants, mds, mds_inv) = Poseidon128Pow5Gen::::constants(); let mds = MDSMatrix(mds); @@ -254,7 +260,7 @@ impl OptimizedPoseidonSpec = vec![[F::zero(); T]; r_f_half]; + let mut constants_start: Vec<[F; T]> = vec![[F::ZERO; T]; r_f_half]; constants_start[0] = constants[0]; for (optimized, constants) in constants_start.iter_mut().skip(1).zip(constants.iter().skip(1)) @@ -264,7 +270,7 @@ impl OptimizedPoseidonSpec OptimizedPoseidonSpec = vec![[F::zero(); T]; r_f_half - 1]; + let mut constants_end: Vec<[F; T]> = vec![[F::ZERO; T]; r_f_half - 1]; for (optimized, constants) in constants_end.iter_mut().zip(constants.iter().skip(r_f_half + r_p + 1)) { @@ -320,20 +325,20 @@ impl OptimizedPoseidonSpec { +struct State { inner: [L; T], _marker: PhantomData, } // the transcript hash implementation is the one suggested in the original paper https://eprint.iacr.org/2019/458.pdf // another reference implementation is https://github.com/privacy-scaling-explorations/halo2wrong/tree/master/transcript/src -impl, const T: usize, const RATE: usize> State { +impl, const T: usize, const RATE: usize> State { fn new(inner: [L; T]) -> Self { Self { inner, _marker: PhantomData } } fn default(loader: &L::Loader) -> Self { - let mut default_state = [F::zero(); T]; + let mut default_state = [F::ZERO; T]; // from Section 4.2 of https://eprint.iacr.org/2019/458.pdf // • Variable-Input-Length Hashing. The capacity value is 2^64 + (o−1) where o the output length. // for our transcript use cases, o = 1 @@ -376,8 +381,8 @@ impl, const T: usize, const RATE: usize> State, const T: usize, const RATE: usize> State, const T: usize, const RATE: usize> State { +pub struct Poseidon { spec: OptimizedPoseidonSpec, default_state: State, state: State, buf: Vec, } -impl, const T: usize, const RATE: usize> Poseidon { +impl, const T: usize, const RATE: usize> Poseidon { /// Initialize a poseidon hasher. /// Generates a new spec with specific number of full and partial rounds. `SECURE_MDS` is usually 0, but may need to be specified because insecure matrices may sometimes be generated pub fn new( loader: &L::Loader, - ) -> Self { + ) -> Self + where + F: FieldExt, + { let default_state = State::default(loader); Self { spec: OptimizedPoseidonSpec::new::(), @@ -495,7 +503,7 @@ impl, const T: usize, const RATE: usize> Poseido self.state.sbox_full(constants); self.state.apply_mds(&mds); } - self.state.sbox_full(&[F::zero(); T]); + self.state.sbox_full(&[F::ZERO; T]); self.state.apply_mds(&mds); } } diff --git a/snark-verifier/src/util/hash/poseidon/tests.rs b/snark-verifier/src/util/hash/poseidon/tests.rs index cf4712bc..76793c91 100644 --- a/snark-verifier/src/util/hash/poseidon/tests.rs +++ b/snark-verifier/src/util/hash/poseidon/tests.rs @@ -47,7 +47,7 @@ fn test_poseidon_against_test_vectors() { hasher.state = State::new(state.try_into().unwrap()); hasher.permutation(&[(); RATE].map(|_| Fr::zero())); // avoid padding let state_0 = hasher.state.inner; - let expected = vec![ + let expected = [ "7853200120776062878684798364095072458815029376092732009249414926327459813530", "7142104613055408817911962100316808866448378443474503659992478482890339429929", "6549537674122432311777789598043107870002137484850126429160507761192163713804", @@ -71,7 +71,7 @@ fn test_poseidon_against_test_vectors() { hasher.state = State::new(state.try_into().unwrap()); hasher.permutation(&[(); RATE].map(|_| Fr::zero())); let state_0 = hasher.state.inner; - let expected = vec![ + let expected = [ "18821383157269793795438455681495246036402687001665670618754263018637548127333", "7817711165059374331357136443537800893307845083525445872661165200086166013245", "16733335996448830230979566039396561240864200624113062088822991822580465420551", diff --git a/snark-verifier/src/util/msm.rs b/snark-verifier/src/util/msm.rs index 8d18cdf8..fef53e59 100644 --- a/snark-verifier/src/util/msm.rs +++ b/snark-verifier/src/util/msm.rs @@ -71,7 +71,7 @@ where let gen = gen.map(|gen| self.bases.first().unwrap().loader().ec_point_load_const(&gen)); let pairs = iter::empty() .chain(self.constant.as_ref().map(|constant| (constant, gen.as_ref().unwrap()))) - .chain(self.scalars.iter().zip(self.bases.into_iter())) + .chain(self.scalars.iter().zip(self.bases)) .collect_vec(); L::multi_scalar_multiplication(&pairs) } diff --git a/snark-verifier/src/util/poly.rs b/snark-verifier/src/util/poly.rs index 17a065f9..9d688a4e 100644 --- a/snark-verifier/src/util/poly.rs +++ b/snark-verifier/src/util/poly.rs @@ -55,7 +55,7 @@ impl Polynomial { /// Returns evaluation at given `x`. pub fn evaluate(&self, x: F) -> F { let evaluate_serial = - |coeffs: &[F]| coeffs.iter().rev().fold(F::zero(), |acc, coeff| acc * x + coeff); + |coeffs: &[F]| coeffs.iter().rev().fold(F::ZERO, |acc, coeff| acc * x + coeff); #[cfg(feature = "parallel")] { @@ -68,7 +68,7 @@ impl Polynomial { } let chunk_size = Integer::div_ceil(&self.len(), &num_threads); - let mut results = vec![F::zero(); num_threads]; + let mut results = vec![F::ZERO; num_threads]; parallelize_iter( results.iter_mut().zip(self.0.chunks(chunk_size)).zip(powers(x.pow_vartime(&[ chunk_size as u64, @@ -78,7 +78,7 @@ impl Polynomial { ]))), |((result, coeffs), scalar)| *result = evaluate_serial(coeffs) * scalar, ); - results.iter().fold(F::zero(), |acc, result| acc + result) + results.iter().fold(F::ZERO, |acc, result| acc + result) } #[cfg(not(feature = "parallel"))] evaluate_serial(&self.0) @@ -133,10 +133,10 @@ impl Mul for Polynomial { type Output = Polynomial; fn mul(mut self, rhs: F) -> Polynomial { - if rhs == F::zero() { - return Polynomial::new(vec![F::zero(); self.len()]); + if rhs == F::ZERO { + return Polynomial::new(vec![F::ZERO; self.len()]); } - if rhs == F::one() { + if rhs == F::ONE { return self; } parallelize(&mut self.0, |(lhs, _)| { diff --git a/snark-verifier/src/verifier/plonk/proof.rs b/snark-verifier/src/verifier/plonk/proof.rs index 7adba7ac..a42a56ae 100644 --- a/snark-verifier/src/verifier/plonk/proof.rs +++ b/snark-verifier/src/verifier/plonk/proof.rs @@ -158,7 +158,7 @@ where .queries .iter() .map(|query| { - let shift = protocol.domain.rotate_scalar(C::Scalar::one(), query.rotation); + let shift = protocol.domain.rotate_scalar(C::Scalar::ONE, query.rotation); pcs::Query::new(query.poly, shift) }) .collect() diff --git a/snark-verifier/src/verifier/plonk/protocol.rs b/snark-verifier/src/verifier/plonk/protocol.rs index a3a84346..97f6f336 100644 --- a/snark-verifier/src/verifier/plonk/protocol.rs +++ b/snark-verifier/src/verifier/plonk/protocol.rs @@ -219,7 +219,7 @@ where let numer = zn_minus_one.clone() * &n_inv; let omegas = langranges .iter() - .map(|&i| loader.load_const(&domain.rotate_scalar(C::Scalar::one(), Rotation(i)))) + .map(|&i| loader.load_const(&domain.rotate_scalar(C::Scalar::ONE, Rotation(i)))) .collect_vec(); let lagrange_evals = omegas .iter() @@ -478,7 +478,7 @@ impl Sum for Expression { impl One for Expression { fn one() -> Self { - Expression::Constant(F::one()) + Expression::Constant(F::ONE) } } From f1d12e52dff42cd9784ac874587c3e563cf94d80 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Fri, 18 Aug 2023 09:00:27 -0600 Subject: [PATCH 07/19] [Feat] Universal verifier circuit (#26) * feat: add example with different vkey as private witness Same aggregation circuit, verifies different snarks with different vkeys (same standard plonk gate, but different selectors / copy constraints) * fix: save break points when generating agg circuit for first time (#23) * fix: save break points when generating agg circuit for first time * chore: add circuit files to gitignore * feat: halo2-lib universal verifier example * chore: cargo fix * feat: allow circuit size (number of rows) to be loaded as witness * chore: clippy fix * fix(n_as_witness): computation of shifts depends on `omega` `omega` which changes when `k` changes, so all shift computations need to be done as witness. Current implementation is likely not the most optimal. Instead of storing `shift` as `omega^i`, we store just `Rotation(i)`. We de-duplicate when possible using `BTreeMap` of `Rotation`. Note you must use `Rotation` instead of `F` for `BTreeMap` because the ordering of `omega^i` may change depending on `omega`. * fix: temp remove pow_var * add universal verifier range check test * chore: do not serialize domain_as_witness if none * Revert "fix: temp remove pow_var" This reverts commit 69f648e12a850a1d16235fc33acebfb5f8b2f290. * fix: halo2_lib example * test: halo2_lib with variable lookup table passes * Bump version to 0.1.3 --------- Co-authored-by: Roshan --- .gitignore | 4 + snark-verifier-sdk/Cargo.toml | 2 +- snark-verifier-sdk/benches/read_pk.rs | 3 +- snark-verifier-sdk/benches/standard_plonk.rs | 5 +- snark-verifier-sdk/examples/n_as_witness.rs | 188 ++++++++++++++++++ snark-verifier-sdk/examples/range_check.rs | 90 +++++++++ .../examples/vkey_as_witness.rs | 184 +++++++++++++++++ snark-verifier-sdk/src/halo2.rs | 34 ++-- snark-verifier-sdk/src/halo2/aggregation.rs | 152 ++++++++++++-- snark-verifier/Cargo.toml | 2 +- snark-verifier/examples/recursion.rs | 2 +- snark-verifier/src/loader.rs | 6 + snark-verifier/src/loader/evm/loader.rs | 4 + snark-verifier/src/loader/halo2/loader.rs | 8 + snark-verifier/src/loader/halo2/shim.rs | 19 ++ snark-verifier/src/loader/native.rs | 7 +- snark-verifier/src/pcs.rs | 24 ++- snark-verifier/src/pcs/ipa/multiopen/bgh19.rs | 90 +++++---- .../src/pcs/kzg/multiopen/bdfg21.rs | 77 ++++--- snark-verifier/src/pcs/kzg/multiopen/gwc19.rs | 35 ++-- snark-verifier/src/system/halo2.rs | 1 + snark-verifier/src/verifier/plonk.rs | 17 +- snark-verifier/src/verifier/plonk/proof.rs | 43 ++-- snark-verifier/src/verifier/plonk/protocol.rs | 94 +++++++-- 24 files changed, 926 insertions(+), 165 deletions(-) create mode 100644 snark-verifier-sdk/examples/n_as_witness.rs create mode 100644 snark-verifier-sdk/examples/range_check.rs create mode 100644 snark-verifier-sdk/examples/vkey_as_witness.rs diff --git a/.gitignore b/.gitignore index 829691c6..ec2971fb 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,7 @@ /target testdata +Cargo.lock +params +agg.pk +break_points.json \ No newline at end of file diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index adf30bec..fa423daf 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snark-verifier-sdk" -version = "0.1.2" +version = "0.1.3" edition = "2021" [dependencies] diff --git a/snark-verifier-sdk/benches/read_pk.rs b/snark-verifier-sdk/benches/read_pk.rs index 55154a2e..f87f52c8 100644 --- a/snark-verifier-sdk/benches/read_pk.rs +++ b/snark-verifier-sdk/benches/read_pk.rs @@ -9,7 +9,7 @@ use halo2_proofs::{halo2curves::bn256::Bn256, poly::kzg::commitment::ParamsKZG}; use pprof::criterion::{Output, PProfProfiler}; use rand::rngs::OsRng; -use snark_verifier_sdk::halo2::aggregation::AggregationConfigParams; +use snark_verifier_sdk::halo2::aggregation::{AggregationConfigParams, VerifierUniversality}; use snark_verifier_sdk::{ gen_pk, halo2::{aggregation::AggregationCircuit, gen_snark_shplonk}, @@ -190,6 +190,7 @@ fn bench(c: &mut Criterion) { None, ¶ms, snarks, + VerifierUniversality::None, ); std::fs::remove_file("examples/agg.pk").ok(); diff --git a/snark-verifier-sdk/benches/standard_plonk.rs b/snark-verifier-sdk/benches/standard_plonk.rs index eecb7140..873f77cb 100644 --- a/snark-verifier-sdk/benches/standard_plonk.rs +++ b/snark-verifier-sdk/benches/standard_plonk.rs @@ -12,7 +12,7 @@ use halo2_proofs::{ use pprof::criterion::{Output, PProfProfiler}; use rand::rngs::OsRng; use snark_verifier_sdk::evm::{evm_verify, gen_evm_proof_shplonk, gen_evm_verifier_shplonk}; -use snark_verifier_sdk::halo2::aggregation::AggregationConfigParams; +use snark_verifier_sdk::halo2::aggregation::{AggregationConfigParams, VerifierUniversality}; use snark_verifier_sdk::{ gen_pk, halo2::{aggregation::AggregationCircuit, gen_proof_shplonk, gen_snark_shplonk}, @@ -193,6 +193,7 @@ fn bench(c: &mut Criterion) { None, ¶ms, snarks.clone(), + VerifierUniversality::None, ); let start0 = start_timer!(|| "gen vk & pk"); @@ -213,6 +214,7 @@ fn bench(c: &mut Criterion) { Some(break_points.clone()), params, snarks.clone(), + VerifierUniversality::None, ); let instances = agg_circuit.instances(); gen_proof_shplonk(params, pk, agg_circuit, instances, None) @@ -230,6 +232,7 @@ fn bench(c: &mut Criterion) { Some(break_points), ¶ms, snarks.clone(), + VerifierUniversality::None, ); let num_instances = agg_circuit.num_instance(); let instances = agg_circuit.instances(); diff --git a/snark-verifier-sdk/examples/n_as_witness.rs b/snark-verifier-sdk/examples/n_as_witness.rs new file mode 100644 index 00000000..3ee25f23 --- /dev/null +++ b/snark-verifier-sdk/examples/n_as_witness.rs @@ -0,0 +1,188 @@ +use halo2_base::gates::builder::CircuitBuilderStage; +use halo2_base::halo2_proofs; +use halo2_base::halo2_proofs::arithmetic::Field; +use halo2_base::halo2_proofs::halo2curves::bn256::Fr; +use halo2_base::halo2_proofs::poly::commitment::Params; +use halo2_base::utils::fs::gen_srs; +use halo2_proofs::halo2curves as halo2_curves; + +use rand::rngs::StdRng; +use rand::SeedableRng; +use snark_verifier_sdk::halo2::aggregation::{AggregationConfigParams, VerifierUniversality}; +use snark_verifier_sdk::SHPLONK; +use snark_verifier_sdk::{ + gen_pk, + halo2::{aggregation::AggregationCircuit, gen_snark_shplonk}, + Snark, +}; + +mod application { + use super::halo2_curves::bn256::Fr; + use super::halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance}, + poly::Rotation, + }; + + use snark_verifier_sdk::CircuitExt; + + #[derive(Clone, Copy)] + pub struct StandardPlonkConfig { + a: Column, + b: Column, + c: Column, + q_a: Column, + q_b: Column, + q_c: Column, + q_ab: Column, + constant: Column, + #[allow(dead_code)] + instance: Column, + } + + impl StandardPlonkConfig { + fn configure(meta: &mut ConstraintSystem) -> Self { + let [a, b, c] = [(); 3].map(|_| meta.advice_column()); + let [q_a, q_b, q_c, q_ab, constant] = [(); 5].map(|_| meta.fixed_column()); + let instance = meta.instance_column(); + + [a, b, c].map(|column| meta.enable_equality(column)); + + meta.create_gate( + "q_a·a + q_b·b + q_c·c + q_ab·a·b + constant + instance = 0", + |meta| { + let [a, b, c] = + [a, b, c].map(|column| meta.query_advice(column, Rotation::cur())); + let [q_a, q_b, q_c, q_ab, constant] = [q_a, q_b, q_c, q_ab, constant] + .map(|column| meta.query_fixed(column, Rotation::cur())); + let instance = meta.query_instance(instance, Rotation::cur()); + Some( + q_a * a.clone() + + q_b * b.clone() + + q_c * c + + q_ab * a * b + + constant + + instance, + ) + }, + ); + + StandardPlonkConfig { a, b, c, q_a, q_b, q_c, q_ab, constant, instance } + } + } + + #[derive(Clone)] + pub struct StandardPlonk(pub Fr, pub usize); + + impl CircuitExt for StandardPlonk { + fn num_instance(&self) -> Vec { + vec![1] + } + + fn instances(&self) -> Vec> { + vec![vec![self.0]] + } + } + + impl Circuit for StandardPlonk { + type Config = StandardPlonkConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self(Fr::zero(), self.1) + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + meta.set_minimum_degree(4); + StandardPlonkConfig::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + layouter.assign_region( + || "", + |mut region| { + region.assign_advice(config.a, 0, Value::known(self.0)); + region.assign_fixed(config.q_a, 0, -Fr::one()); + region.assign_advice(config.a, 1, Value::known(-Fr::from(5u64))); + for (idx, column) in (1..).zip([ + config.q_a, + config.q_b, + config.q_c, + config.q_ab, + config.constant, + ]) { + region.assign_fixed(column, 1, Fr::from(idx as u64)); + } + let a = region.assign_advice(config.a, 2, Value::known(Fr::one())); + a.copy_advice(&mut region, config.b, 3); + a.copy_advice(&mut region, config.c, 4); + + // assuming <= 10 blinding factors + // fill in most of circuit with a computation + let n = self.1; + for offset in 5..n - 10 { + region.assign_advice(config.a, offset, Value::known(-Fr::from(5u64))); + for (idx, column) in (1..).zip([ + config.q_a, + config.q_b, + config.q_c, + config.q_ab, + config.constant, + ]) { + region.assign_fixed(column, offset, Fr::from(idx as u64)); + } + } + + Ok(()) + }, + ) + } + } +} + +fn gen_application_snark(k: u32) -> Snark { + let rng = StdRng::seed_from_u64(0); + let params = gen_srs(k); + let circuit = application::StandardPlonk(Fr::random(rng), params.n() as usize); + + let pk = gen_pk(¶ms, &circuit, None); + gen_snark_shplonk(¶ms, &pk, circuit, None::<&str>) +} + +fn main() { + let dummy_snark = gen_application_snark(8); + + let k = 15u32; + let params = gen_srs(k); + let lookup_bits = k as usize - 1; + let mut agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Keygen, + AggregationConfigParams { degree: k, lookup_bits, ..Default::default() }, + None, + ¶ms, + vec![dummy_snark], + VerifierUniversality::Full, + ); + let agg_config = agg_circuit.config(Some(10)); + + let pk = gen_pk(¶ms, &agg_circuit, None); + let break_points = agg_circuit.break_points(); + + let snarks = [8, 12, 15, 20].map(|k| (k, gen_application_snark(k))); + for (k, snark) in snarks { + let agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Prover, + agg_config, + Some(break_points.clone()), + ¶ms, + vec![snark], + VerifierUniversality::Full, + ); + let _snark = gen_snark_shplonk(¶ms, &pk, agg_circuit, None::<&str>); + println!("snark with k = {k} success"); + } +} diff --git a/snark-verifier-sdk/examples/range_check.rs b/snark-verifier-sdk/examples/range_check.rs new file mode 100644 index 00000000..c9200df7 --- /dev/null +++ b/snark-verifier-sdk/examples/range_check.rs @@ -0,0 +1,90 @@ +use ark_std::{end_timer, start_timer}; +use halo2_base::gates::builder::{ + BaseConfigParams, CircuitBuilderStage, GateThreadBuilder, RangeWithInstanceCircuitBuilder, +}; +use halo2_base::gates::flex_gate::GateStrategy; +use halo2_base::halo2_proofs::halo2curves::bn256::Fr; +use halo2_base::halo2_proofs::plonk::Circuit; +use halo2_base::safe_types::{GateInstructions, RangeChip, RangeInstructions}; +use halo2_base::utils::fs::gen_srs; + +use itertools::Itertools; +use snark_verifier_sdk::halo2::aggregation::{AggregationConfigParams, VerifierUniversality}; +use snark_verifier_sdk::SHPLONK; +use snark_verifier_sdk::{ + gen_pk, + halo2::{aggregation::AggregationCircuit, gen_snark_shplonk}, + Snark, +}; + +fn generate_circuit(k: u32) -> Snark { + let mut builder = GateThreadBuilder::new(false); + let ctx = builder.main(0); + let lookup_bits = k as usize - 1; + let range = RangeChip::::default(lookup_bits); + + let x = ctx.load_witness(Fr::from(14)); + range.range_check(ctx, x, 2 * lookup_bits + 1); + range.gate().add(ctx, x, x); + + let circuit = RangeWithInstanceCircuitBuilder::::keygen( + builder.clone(), + BaseConfigParams { + strategy: GateStrategy::Vertical, + k: k as usize, + num_advice_per_phase: vec![1], + num_lookup_advice_per_phase: vec![1], + num_fixed: 1, + lookup_bits: Some(lookup_bits), + }, + vec![], + ); + let params = gen_srs(k); + + let pk = gen_pk(¶ms, &circuit, None); + let breakpoints = circuit.break_points(); + + let circuit = RangeWithInstanceCircuitBuilder::::prover( + builder.clone(), + circuit.params(), + breakpoints, + vec![], + ); + gen_snark_shplonk(¶ms, &pk, circuit, None::<&str>) +} + +fn main() { + let dummy_snark = generate_circuit(13); + + let k = 14u32; + let lookup_bits = k as usize - 1; + let params = gen_srs(k); + let mut agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Keygen, + AggregationConfigParams { degree: k, lookup_bits, ..Default::default() }, + None, + ¶ms, + vec![dummy_snark], + VerifierUniversality::Full, + ); + let agg_config = agg_circuit.config(Some(10)); + + let start0 = start_timer!(|| "gen vk & pk"); + let pk = gen_pk(¶ms, &agg_circuit, None); + end_timer!(start0); + let break_points = agg_circuit.break_points(); + + let snarks = (14..17).map(generate_circuit).collect_vec(); + for (i, snark) in snarks.into_iter().enumerate() { + let agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Prover, + agg_config, + Some(break_points.clone()), + ¶ms, + vec![snark], + VerifierUniversality::Full, + ); + let _snark = gen_snark_shplonk(¶ms, &pk, agg_circuit, None::<&str>); + println!("snark {i} success"); + } +} diff --git a/snark-verifier-sdk/examples/vkey_as_witness.rs b/snark-verifier-sdk/examples/vkey_as_witness.rs new file mode 100644 index 00000000..a0eb30d2 --- /dev/null +++ b/snark-verifier-sdk/examples/vkey_as_witness.rs @@ -0,0 +1,184 @@ +use application::ComputeFlag; + +use halo2_base::gates::builder::CircuitBuilderStage; +use halo2_base::halo2_proofs; +use halo2_base::halo2_proofs::arithmetic::Field; +use halo2_base::halo2_proofs::halo2curves::bn256::Fr; +use halo2_base::utils::fs::gen_srs; +use halo2_proofs::halo2curves as halo2_curves; + +use halo2_proofs::{halo2curves::bn256::Bn256, poly::kzg::commitment::ParamsKZG}; +use rand::rngs::OsRng; +use snark_verifier_sdk::halo2::aggregation::{AggregationConfigParams, VerifierUniversality}; +use snark_verifier_sdk::SHPLONK; +use snark_verifier_sdk::{ + gen_pk, + halo2::{aggregation::AggregationCircuit, gen_snark_shplonk}, + Snark, +}; + +mod application { + use super::halo2_curves::bn256::Fr; + use super::halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance}, + poly::Rotation, + }; + + use snark_verifier_sdk::CircuitExt; + + #[derive(Clone, Copy)] + pub struct StandardPlonkConfig { + a: Column, + b: Column, + c: Column, + q_a: Column, + q_b: Column, + q_c: Column, + q_ab: Column, + constant: Column, + #[allow(dead_code)] + instance: Column, + } + + impl StandardPlonkConfig { + fn configure(meta: &mut ConstraintSystem) -> Self { + let [a, b, c] = [(); 3].map(|_| meta.advice_column()); + let [q_a, q_b, q_c, q_ab, constant] = [(); 5].map(|_| meta.fixed_column()); + let instance = meta.instance_column(); + + [a, b, c].map(|column| meta.enable_equality(column)); + + meta.create_gate( + "q_a·a + q_b·b + q_c·c + q_ab·a·b + constant + instance = 0", + |meta| { + let [a, b, c] = + [a, b, c].map(|column| meta.query_advice(column, Rotation::cur())); + let [q_a, q_b, q_c, q_ab, constant] = [q_a, q_b, q_c, q_ab, constant] + .map(|column| meta.query_fixed(column, Rotation::cur())); + let instance = meta.query_instance(instance, Rotation::cur()); + Some( + q_a * a.clone() + + q_b * b.clone() + + q_c * c + + q_ab * a * b + + constant + + instance, + ) + }, + ); + + StandardPlonkConfig { a, b, c, q_a, q_b, q_c, q_ab, constant, instance } + } + } + + #[derive(Clone, Copy, PartialEq, Eq)] + pub enum ComputeFlag { + All, + SkipFixed, + SkipCopy, + } + + #[derive(Clone)] + pub struct StandardPlonk(pub Fr, pub ComputeFlag); + + impl CircuitExt for StandardPlonk { + fn num_instance(&self) -> Vec { + vec![1] + } + + fn instances(&self) -> Vec> { + vec![vec![self.0]] + } + } + + impl Circuit for StandardPlonk { + type Config = StandardPlonkConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self(Fr::zero(), self.1) + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + meta.set_minimum_degree(4); + StandardPlonkConfig::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + layouter.assign_region( + || "", + |mut region| { + region.assign_advice(config.a, 0, Value::known(self.0)); + region.assign_fixed(config.q_a, 0, -Fr::one()); + region.assign_advice(config.a, 1, Value::known(-Fr::from(5u64))); + if self.1 != ComputeFlag::SkipFixed { + for (idx, column) in (1..).zip([ + config.q_a, + config.q_b, + config.q_c, + config.q_ab, + config.constant, + ]) { + region.assign_fixed(column, 1, Fr::from(idx as u64)); + } + } + let a = region.assign_advice(config.a, 2, Value::known(Fr::one())); + if self.1 != ComputeFlag::SkipCopy { + a.copy_advice(&mut region, config.b, 3); + a.copy_advice(&mut region, config.c, 4); + } + + Ok(()) + }, + ) + } + } +} + +fn gen_application_snark(params: &ParamsKZG, flag: ComputeFlag) -> Snark { + let circuit = application::StandardPlonk(Fr::random(OsRng), flag); + + let pk = gen_pk(params, &circuit, None); + gen_snark_shplonk(params, &pk, circuit, None::<&str>) +} + +fn main() { + let params_app = gen_srs(8); + let dummy_snark = gen_application_snark(¶ms_app, ComputeFlag::All); + + let k = 15u32; + let params = gen_srs(k); + let lookup_bits = k as usize - 1; + let mut agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Keygen, + AggregationConfigParams { degree: k, lookup_bits, ..Default::default() }, + None, + ¶ms, + vec![dummy_snark], + VerifierUniversality::PreprocessedAsWitness, + ); + let agg_config = agg_circuit.config(Some(10)); + + let pk = gen_pk(¶ms, &agg_circuit, None); + let break_points = agg_circuit.break_points(); + + let snarks = [ComputeFlag::All, ComputeFlag::SkipFixed, ComputeFlag::SkipCopy] + .map(|flag| gen_application_snark(¶ms_app, flag)); + for (i, snark) in snarks.into_iter().enumerate() { + let agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Prover, + agg_config, + Some(break_points.clone()), + ¶ms, + vec![snark], + VerifierUniversality::PreprocessedAsWitness, + ); + let _snark = gen_snark_shplonk(¶ms, &pk, agg_circuit, None::<&str>); + println!("snark {i} success"); + } +} diff --git a/snark-verifier-sdk/src/halo2.rs b/snark-verifier-sdk/src/halo2.rs index b0710230..06d5e622 100644 --- a/snark-verifier-sdk/src/halo2.rs +++ b/snark-verifier-sdk/src/halo2.rs @@ -35,6 +35,7 @@ use snark_verifier::{ AccumulationScheme, PolynomialCommitmentScheme, Query, }, system::halo2::{compile, Config}, + util::arithmetic::Rotation, util::transcript::TranscriptWrite, verifier::plonk::PlonkProof, }; @@ -122,20 +123,25 @@ where end_timer!(proof_time); // validate proof before caching - assert!({ - let mut transcript_read = - PoseidonTranscript::::from_spec(&proof[..], POSEIDON_SPEC.clone()); - VerificationStrategy::<_, V>::finalize( - verify_proof::<_, V, _, _, _>( - params.verifier_params(), - pk.get_vk(), - AccumulatorStrategy::new(params.verifier_params()), - &[instances.as_slice()], - &mut transcript_read, + assert!( + { + let mut transcript_read = PoseidonTranscript::::from_spec( + &proof[..], + POSEIDON_SPEC.clone(), + ); + VerificationStrategy::<_, V>::finalize( + verify_proof::<_, V, _, _, _>( + params.verifier_params(), + pk.get_vk(), + AccumulatorStrategy::new(params.verifier_params()), + &[instances.as_slice()], + &mut transcript_read, + ) + .unwrap(), ) - .unwrap(), - ) - }); + }, + "SNARK proof failed to verify" + ); if let Some((instance_path, proof_path)) = path { write_instances(&instances, instance_path); @@ -286,7 +292,7 @@ where NativeLoader, Accumulator = KzgAccumulator, VerifyingKey = KzgAsVerifyingKey, - > + CostEstimation>>, + > + CostEstimation>>, { struct CsProxy(PhantomData<(F, C)>); diff --git a/snark-verifier-sdk/src/halo2/aggregation.rs b/snark-verifier-sdk/src/halo2/aggregation.rs index 2d093f7b..0063a599 100644 --- a/snark-verifier-sdk/src/halo2/aggregation.rs +++ b/snark-verifier-sdk/src/halo2/aggregation.rs @@ -43,6 +43,37 @@ pub type Svk = KzgSuccinctVerifyingKey; pub type BaseFieldEccChip<'chip> = halo2_ecc::ecc::BaseFieldEccChip<'chip, G1Affine>; pub type Halo2Loader<'chip> = loader::halo2::Halo2Loader>; +pub struct SnarkAggregationWitness<'a> { + pub previous_instances: Vec>>, + pub accumulator: KzgAccumulator>>, + /// This returns the assigned `preprocessed` and `transcript_initial_state` values as a vector of assigned values, one for each aggregated snark. + /// These can then be exposed as public instances. + /// + /// This is only useful if preprocessed digest is loaded as witness (i.e., `preprocessed_as_witness` is true in `aggregate`), so we set it to `None` otherwise. + pub preprocessed_digests: Option>>>, +} + +/// Different possible stages of universality the aggregation circuit can support +#[derive(PartialEq, Eq, Clone, Copy, Debug)] +pub enum VerifierUniversality { + /// Default: verifier is specific to a single circuit + None, + /// Preprocessed digest (commitments to fixed columns) is loaded as witness + PreprocessedAsWitness, + /// Preprocessed as witness and number of rows in the circuit `n` loaded as witness + Full, +} + +impl VerifierUniversality { + pub fn preprocessed_as_witness(&self) -> bool { + self != &VerifierUniversality::None + } + + pub fn n_as_witness(&self) -> bool { + self == &VerifierUniversality::Full + } +} + #[allow(clippy::type_complexity)] /// Core function used in `synthesize` to aggregate multiple `snarks`. /// @@ -50,6 +81,9 @@ pub type Halo2Loader<'chip> = loader::halo2::Halo2Loader( @@ -57,7 +91,8 @@ pub fn aggregate<'a, AS>( loader: &Rc>, snarks: &[Snark], as_proof: &[u8], -) -> (Vec>>, KzgAccumulator>>) + universality: VerifierUniversality, +) -> SnarkAggregationWitness<'a> where AS: PolynomialCommitmentScheme< G1Affine, @@ -82,6 +117,7 @@ where }; let mut previous_instances = Vec::with_capacity(snarks.len()); + let mut preprocessed_digests = Vec::with_capacity(snarks.len()); // to avoid re-loading the spec each time, we create one transcript and clear the stream let mut transcript = PoseidonTranscript::>, &[u8]>::from_spec( loader, @@ -89,10 +125,42 @@ where POSEIDON_SPEC.clone(), ); + let preprocessed_as_witness = universality.preprocessed_as_witness(); let mut accumulators = snarks .iter() - .flat_map(|snark| { - let protocol = snark.protocol.loaded(loader); + .flat_map(|snark: &Snark| { + let protocol = if preprocessed_as_witness { + // always load `domain.n` as witness if vkey is witness + snark.protocol.loaded_preprocessed_as_witness(loader, universality.n_as_witness()) + } else { + snark.protocol.loaded(loader) + }; + let inputs = protocol + .preprocessed + .iter() + .flat_map(|preprocessed| { + let assigned = preprocessed.assigned(); + [assigned.x(), assigned.y()] + .into_iter() + .flat_map(|coordinate| coordinate.limbs().to_vec()) + .collect_vec() + }) + .chain( + protocol.transcript_initial_state.clone().map(|scalar| scalar.into_assigned()), + ) + .chain( + protocol + .domain_as_witness + .as_ref() + .map(|domain| domain.n.clone().into_assigned()), + ) // If `n` is witness, add it as part of input + .chain( + protocol + .domain_as_witness + .as_ref() + .map(|domain| domain.gen.clone().into_assigned()), + ) // If `n` is witness, add the generator of the order `n` subgroup as part of input + .collect_vec(); let instances = assign_instances(&snark.instances); // read the transcript and perform Fiat-Shamir @@ -111,6 +179,7 @@ where previous_instances.push( instances.into_iter().flatten().map(|scalar| scalar.into_assigned()).collect(), ); + preprocessed_digests.push(inputs); accumulator }) @@ -129,8 +198,9 @@ where } else { accumulators.pop().unwrap() }; + let preprocessed_digests = preprocessed_as_witness.then_some(preprocessed_digests); - (previous_instances, accumulator) + SnarkAggregationWitness { previous_instances, accumulator, preprocessed_digests } } /// Same as `FlexGateConfigParams` except we assume a single Phase and default 'Vertical' strategy. @@ -187,6 +257,14 @@ impl TryFrom<&BaseConfigParams> for AggregationConfigParams { } } +impl TryFrom for AggregationConfigParams { + type Error = &'static str; + + fn try_from(value: BaseConfigParams) -> Result { + Self::try_from(&value) + } +} + /// Holds virtual contexts for the cells used to verify a collection of snarks #[derive(Clone, Debug)] pub struct AggregationCtxBuilder { @@ -196,6 +274,11 @@ pub struct AggregationCtxBuilder { pub accumulator: Vec>, // the public instances from previous snarks that were aggregated pub previous_instances: Vec>>, + /// This returns the assigned `preprocessed_digest` (vkey), optional `transcript_initial_state`, `domain.n` (optional), and `omega` (optional) values as a vector of assigned values, one for each aggregated snark. + /// These can then be exposed as public instances. + /// + /// This is only useful if preprocessed digest is loaded as witness (i.e., `universality != None`), so we set it to `None` if `universality == None`. + pub preprocessed_digests: Option>>>, } #[derive(Clone, Debug)] @@ -204,6 +287,11 @@ pub struct AggregationCircuit { // the public instances from previous snarks that were aggregated, now collected as PRIVATE assigned values // the user can optionally append these to `inner.assigned_instances` to expose them pub previous_instances: Vec>>, + /// This returns the assigned `preprocessed_digest` (vkey), optional `transcript_initial_state`, `domain.n` (optional), and `omega` (optional) values as a vector of assigned values, one for each aggregated snark. + /// These can then be exposed as public instances. + /// + /// This is only useful if preprocessed digest is loaded as witness (i.e., `universality != None`), so we set it to `None` if `universality == None`. + pub preprocessed_digests: Option>>>, // accumulation scheme proof, private input // pub as_proof: Vec, } @@ -236,13 +324,21 @@ impl AggregationCtxBuilder { /// /// Also returns the limbs of the pair of elliptic curve points, referred to as the `accumulator`, that need to be verified in a final pairing check. /// - /// Warning: will fail silently if `snarks` were created using a different multi-open scheme than `AS` + /// # Universality + /// - If `universality` is not `None`, then the verifying keys of each snark in `snarks` is loaded as a witness in the circuit. + /// - Moreover, if `universality` is `Full`, then the number of rows `n` of each snark in `snarks` is also loaded as a witness. In this case the generator `omega` of the order `n` multiplicative subgroup of `F` is also loaded as a witness. + /// - By default, these witnesses are _private_ and returned in `self.preprocessed_ + /// - The user can optionally modify the circuit after calling this function to add more instances to `assigned_instances` to expose. + /// + /// # Warning + /// Will fail silently if `snarks` were created using a different multi-open scheme than `AS` /// where `AS` can be either [`crate::SHPLONK`] or [`crate::GWC`] (for original PLONK multi-open scheme) pub fn new( witness_gen_only: bool, lookup_bits: usize, params: &ParamsKZG, snarks: impl IntoIterator, + universality: VerifierUniversality, ) -> Self where AS: for<'a> Halo2KzgAccumulationScheme<'a>, @@ -289,8 +385,8 @@ impl AggregationCtxBuilder { let ecc_chip = BaseFieldEccChip::new(&fp_chip); let loader = Halo2Loader::new(ecc_chip, builder); - let (previous_instances, accumulator) = - aggregate::(&svk, &loader, &snarks, as_proof.as_slice()); + let SnarkAggregationWitness { previous_instances, accumulator, preprocessed_digests } = + aggregate::(&svk, &loader, &snarks, as_proof.as_slice(), universality); let lhs = accumulator.lhs.assigned(); let rhs = accumulator.rhs.assigned(); let accumulator = lhs @@ -314,7 +410,7 @@ impl AggregationCtxBuilder { } let builder = loader.take_ctx(); - Self { builder, accumulator, previous_instances } + Self { builder, accumulator, previous_instances, preprocessed_digests } } } @@ -322,6 +418,8 @@ impl AggregationCircuit { /// Given snarks, this creates a circuit and runs the `GateThreadBuilder` to verify all the snarks. /// By default, the returned circuit has public instances equal to the limbs of the pair of elliptic curve points, referred to as the `accumulator`, that need to be verified in a final pairing check. /// + /// See [`AggregationCtxBuilder`] for more details. + /// /// The user can optionally modify the circuit after calling this function to add more instances to `assigned_instances` to expose. /// /// Warning: will fail silently if `snarks` were created using a different multi-open scheme than `AS` @@ -332,17 +430,23 @@ impl AggregationCircuit { break_points: Option, params: &ParamsKZG, snarks: impl IntoIterator, + universality: VerifierUniversality, ) -> Self where AS: for<'a> Halo2KzgAccumulationScheme<'a>, { - let AggregationCtxBuilder { builder, accumulator, previous_instances } = - AggregationCtxBuilder::new::( - stage == CircuitBuilderStage::Prover, - agg_config.lookup_bits, - params, - snarks, - ); + let AggregationCtxBuilder { + builder, + accumulator, + previous_instances, + preprocessed_digests, + } = AggregationCtxBuilder::new::( + stage == CircuitBuilderStage::Prover, + agg_config.lookup_bits, + params, + snarks, + universality, + ); let inner = RangeWithInstanceCircuitBuilder::from_stage( stage, builder, @@ -350,7 +454,7 @@ impl AggregationCircuit { break_points, accumulator, ); - Self { inner, previous_instances } + Self { inner, previous_instances, preprocessed_digests } } pub fn public( @@ -364,7 +468,14 @@ impl AggregationCircuit { where AS: for<'a> Halo2KzgAccumulationScheme<'a>, { - let mut private = Self::new::(stage, agg_config, break_points, params, snarks); + let mut private = Self::new::( + stage, + agg_config, + break_points, + params, + snarks, + VerifierUniversality::None, + ); private.expose_previous_instances(has_prev_accumulator); private } @@ -380,11 +491,8 @@ impl AggregationCircuit { } /// Auto-configure the circuit and change the circuit's internal configuration parameters. - pub fn config(&mut self, k: u32, minimum_rows: Option) -> BaseConfigParams { - let mut new_config = self.inner.circuit.0.builder.borrow().config(k as usize, minimum_rows); - new_config.lookup_bits = self.inner.circuit.0.config_params.lookup_bits; - self.inner.circuit.0.config_params = new_config.clone(); - new_config + pub fn config(&mut self, minimum_rows: Option) -> AggregationConfigParams { + self.inner.config(minimum_rows).try_into().unwrap() } pub fn break_points(&self) -> MultiPhaseThreadBreakPoints { diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index 5606df37..ebbf283b 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snark-verifier" -version = "0.1.2" +version = "0.1.3" edition = "2021" [dependencies] diff --git a/snark-verifier/examples/recursion.rs b/snark-verifier/examples/recursion.rs index b469a51a..9c9b169a 100644 --- a/snark-verifier/examples/recursion.rs +++ b/snark-verifier/examples/recursion.rs @@ -373,7 +373,7 @@ mod recursion { ) -> (Vec>>, Vec>>>) { let protocol = if let Some(preprocessed_digest) = preprocessed_digest { let preprocessed_digest = loader.scalar_from_assigned(preprocessed_digest); - let protocol = snark.protocol.loaded_preprocessed_as_witness(loader); + let protocol = snark.protocol.loaded_preprocessed_as_witness(loader, false); let inputs = protocol .preprocessed .iter() diff --git a/snark-verifier/src/loader.rs b/snark-verifier/src/loader.rs index a3637f08..26450e1a 100644 --- a/snark-verifier/src/loader.rs +++ b/snark-verifier/src/loader.rs @@ -67,6 +67,12 @@ pub trait LoadedScalar: Clone + Debug + PartialEq + FieldOps { acc } + /// Returns power to exponent, where exponent is also [`LoadedScalar`]. + /// If `Loader` is for Halo2, then `exp` must have at most `exp_max_bits` bits (otherwise constraints will fail). + /// + /// Currently **unimplemented** for EvmLoader + fn pow_var(&self, exp: &Self, exp_max_bits: usize) -> Self; + /// Returns powers up to exponent `n-1`. fn powers(&self, n: usize) -> Vec { iter::once(self.loader().load_one()) diff --git a/snark-verifier/src/loader/evm/loader.rs b/snark-verifier/src/loader/evm/loader.rs index bfb37c8c..ba304f2b 100644 --- a/snark-verifier/src/loader/evm/loader.rs +++ b/snark-verifier/src/loader/evm/loader.rs @@ -632,6 +632,10 @@ impl> LoadedScalar for Scalar { fn loader(&self) -> &Self::Loader { &self.loader } + + fn pow_var(&self, _exp: &Self, _exp_max_bits: usize) -> Self { + todo!() + } } impl EcPointLoader for Rc diff --git a/snark-verifier/src/loader/halo2/loader.rs b/snark-verifier/src/loader/halo2/loader.rs index 105972c0..f8e1da7d 100644 --- a/snark-verifier/src/loader/halo2/loader.rs +++ b/snark-verifier/src/loader/halo2/loader.rs @@ -306,6 +306,14 @@ impl> LoadedScalar for Sc fn loader(&self) -> &Self::Loader { &self.loader } + + fn pow_var(&self, exp: &Self, max_bits: usize) -> Self { + let loader = self.loader(); + let base = self.clone().into_assigned(); + let exp = exp.clone().into_assigned(); + let res = loader.scalar_chip().pow_var(&mut loader.ctx_mut(), &base, &exp, max_bits); + loader.scalar_from_assigned(res) + } } impl> Debug for Scalar { diff --git a/snark-verifier/src/loader/halo2/shim.rs b/snark-verifier/src/loader/halo2/shim.rs index 9d010d2b..49bbad41 100644 --- a/snark-verifier/src/loader/halo2/shim.rs +++ b/snark-verifier/src/loader/halo2/shim.rs @@ -65,6 +65,15 @@ pub trait IntegerInstructions: Clone + Debug { lhs: &Self::AssignedInteger, rhs: &Self::AssignedInteger, ); + + /// Returns `base^exponent` and constrains that `exponent` has at most `max_bits` bits. + fn pow_var( + &self, + ctx: &mut Self::Context, + base: &Self::AssignedInteger, + exponent: &Self::AssignedInteger, + max_bits: usize, + ) -> Self::AssignedInteger; } /// Instructions to handle elliptic curve point operations. @@ -233,6 +242,16 @@ mod halo2_lib { ) { ctx.main(0).constrain_equal(a, b); } + + fn pow_var( + &self, + ctx: &mut Self::Context, + base: &Self::AssignedInteger, + exponent: &Self::AssignedInteger, + max_bits: usize, + ) -> Self::AssignedInteger { + GateInstructions::pow_var(self, ctx.main(0), *base, *exponent, max_bits) + } } impl<'chip, C: CurveAffineExt> EccInstructions for BaseFieldEccChip<'chip, C> diff --git a/snark-verifier/src/loader/native.rs b/snark-verifier/src/loader/native.rs index 783aaa89..a9aa86ff 100644 --- a/snark-verifier/src/loader/native.rs +++ b/snark-verifier/src/loader/native.rs @@ -2,7 +2,7 @@ use crate::{ loader::{EcPointLoader, LoadedEcPoint, LoadedScalar, Loader, ScalarLoader}, - util::arithmetic::{Curve, CurveAffine, FieldOps, PrimeField}, + util::arithmetic::{fe_to_big, Curve, CurveAffine, FieldOps, PrimeField}, Error, }; use lazy_static::lazy_static; @@ -38,6 +38,11 @@ impl LoadedScalar for F { fn loader(&self) -> &NativeLoader { &LOADER } + + fn pow_var(&self, exp: &Self, _: usize) -> Self { + let exp = fe_to_big(*exp).to_u64_digits(); + self.pow_vartime(exp) + } } impl EcPointLoader for NativeLoader { diff --git a/snark-verifier/src/pcs.rs b/snark-verifier/src/pcs.rs index 65b1325b..1ca9eedc 100644 --- a/snark-verifier/src/pcs.rs +++ b/snark-verifier/src/pcs.rs @@ -3,7 +3,7 @@ use crate::{ loader::{native::NativeLoader, Loader}, util::{ - arithmetic::{CurveAffine, PrimeField}, + arithmetic::{CurveAffine, Rotation}, msm::Msm, transcript::{TranscriptRead, TranscriptWrite}, }, @@ -18,24 +18,26 @@ pub mod kzg; /// Query to an oracle. /// It assumes all queries are based on the same point, but with some `shift`. #[derive(Clone, Debug)] -pub struct Query { +pub struct Query { /// Index of polynomial to query pub poly: usize, /// Shift of the query point. - pub shift: F, + pub shift: S, + /// Shift loaded as either constant or witness. It is user's job to ensure this is correctly constrained to have value equal to `shift` + pub loaded_shift: T, /// Evaluation read from transcript. pub eval: T, } -impl Query { +impl Query { /// Initialize [`Query`] without evaluation. - pub fn new(poly: usize, shift: F) -> Self { - Self { poly, shift, eval: () } + pub fn new(poly: usize, shift: S) -> Self { + Self { poly, shift, loaded_shift: (), eval: () } } - /// Returns [`Query`] with evaluation. - pub fn with_evaluation(self, eval: T) -> Query { - Query { poly: self.poly, shift: self.shift, eval } + /// Returns [`Query`] with evaluation and optionally the shift are loaded as. + pub fn with_evaluation(self, loaded_shift: T, eval: T) -> Query { + Query { poly: self.poly, shift: self.shift, loaded_shift, eval } } } @@ -55,7 +57,7 @@ where /// Read [`PolynomialCommitmentScheme::Proof`] from transcript. fn read_proof( vk: &Self::VerifyingKey, - queries: &[Query], + queries: &[Query], transcript: &mut T, ) -> Result where @@ -66,7 +68,7 @@ where vk: &Self::VerifyingKey, commitments: &[Msm], point: &L::LoadedScalar, - queries: &[Query], + queries: &[Query], proof: &Self::Proof, ) -> Result; } diff --git a/snark-verifier/src/pcs/ipa/multiopen/bgh19.rs b/snark-verifier/src/pcs/ipa/multiopen/bgh19.rs index 538aa4fb..e2cb87ab 100644 --- a/snark-verifier/src/pcs/ipa/multiopen/bgh19.rs +++ b/snark-verifier/src/pcs/ipa/multiopen/bgh19.rs @@ -5,7 +5,7 @@ use crate::{ PolynomialCommitmentScheme, Query, }, util::{ - arithmetic::{CurveAffine, Fraction, PrimeField}, + arithmetic::{CurveAffine, Fraction, PrimeField, Rotation}, msm::Msm, transcript::TranscriptRead, Itertools, @@ -35,7 +35,7 @@ where fn read_proof( svk: &Self::VerifyingKey, - queries: &[Query], + queries: &[Query], transcript: &mut T, ) -> Result where @@ -48,7 +48,7 @@ where svk: &Self::VerifyingKey, commitments: &[Msm], x: &L::LoadedScalar, - queries: &[Query], + queries: &[Query], proof: &Self::Proof, ) -> Result { let loader = x.loader(); @@ -119,7 +119,7 @@ where { fn read>( svk: &IpaSuccinctVerifyingKey, - queries: &[Query], + queries: &[Query], transcript: &mut T, ) -> Result { // Multiopen @@ -157,28 +157,33 @@ where } } -fn query_sets(queries: &[Query]) -> Vec> +fn query_sets(queries: &[Query]) -> Vec> where - F: PrimeField + Ord, + S: PartialEq + Ord + Copy, T: Clone, { let poly_shifts = - queries.iter().fold(Vec::<(usize, Vec, Vec<&T>)>::new(), |mut poly_shifts, query| { + queries.iter().fold(Vec::<(usize, Vec<_>, Vec<&T>)>::new(), |mut poly_shifts, query| { if let Some(pos) = poly_shifts.iter().position(|(poly, _, _)| *poly == query.poly) { let (_, shifts, evals) = &mut poly_shifts[pos]; - if !shifts.contains(&query.shift) { - shifts.push(query.shift); + if !shifts.iter().map(|(shift, _)| shift).contains(&query.shift) { + shifts.push((query.shift, query.loaded_shift.clone())); evals.push(&query.eval); } } else { - poly_shifts.push((query.poly, vec![query.shift], vec![&query.eval])); + poly_shifts.push(( + query.poly, + vec![(query.shift, query.loaded_shift.clone())], + vec![&query.eval], + )); } poly_shifts }); - poly_shifts.into_iter().fold(Vec::>::new(), |mut sets, (poly, shifts, evals)| { + poly_shifts.into_iter().fold(Vec::>::new(), |mut sets, (poly, shifts, evals)| { if let Some(pos) = sets.iter().position(|set| { - BTreeSet::from_iter(set.shifts.iter()) == BTreeSet::from_iter(shifts.iter()) + BTreeSet::from_iter(set.shifts.iter().map(|(shift, _)| shift)) + == BTreeSet::from_iter(shifts.iter().map(|(shift, _)| shift)) }) { let set = &mut sets[pos]; if !set.polys.contains(&poly) { @@ -187,7 +192,7 @@ where set.shifts .iter() .map(|lhs| { - let idx = shifts.iter().position(|rhs| lhs == rhs).unwrap(); + let idx = shifts.iter().position(|rhs| lhs.0 == rhs.0).unwrap(); evals[idx] }) .collect(), @@ -201,18 +206,23 @@ where }) } -fn query_set_coeffs(sets: &[QuerySet], x: &T, x_3: &T) -> Vec> +fn query_set_coeffs( + sets: &[QuerySet], + x: &T, + x_3: &T, +) -> Vec> where F: PrimeField + Ord, T: LoadedScalar, { - let loader = x.loader(); - let superset = sets.iter().flat_map(|set| set.shifts.clone()).sorted().dedup(); + let superset = BTreeMap::from_iter(sets.iter().flat_map(|set| set.shifts.clone())); let size = sets.iter().map(|set| set.shifts.len()).chain(Some(2)).max().unwrap(); let powers_of_x = x.powers(size); let x_3_minus_x_shift_i = BTreeMap::from_iter( - superset.map(|shift| (shift, x_3.clone() - x.clone() * loader.load_const(&shift))), + superset + .into_iter() + .map(|(shift, loaded_shift)| (shift, x_3.clone() - x.clone() * loaded_shift)), ); let mut coeffs = sets @@ -228,23 +238,22 @@ where } #[derive(Clone, Debug)] -struct QuerySet<'a, F, T> { - shifts: Vec, +struct QuerySet<'a, S, T> { + shifts: Vec<(S, T)>, polys: Vec, evals: Vec>, } -impl<'a, F, T> QuerySet<'a, F, T> -where - F: PrimeField, - T: LoadedScalar, -{ +impl<'a, S, T> QuerySet<'a, S, T> { fn msm>( &self, commitments: &[Msm<'a, C, L>], q_eval: &T, powers_of_x_1: &[T], - ) -> Msm { + ) -> Msm + where + T: LoadedScalar, + { self.polys .iter() .rev() @@ -254,7 +263,15 @@ where - Msm::constant(q_eval.clone()) } - fn f_eval(&self, coeff: &QuerySetCoeff, q_eval: &T, powers_of_x_1: &[T]) -> T { + fn f_eval( + &self, + coeff: &QuerySetCoeff, + q_eval: &T, + powers_of_x_1: &[T], + ) -> T + where + T: LoadedScalar, + { let loader = q_eval.loader(); let r_eval = { let r_evals = self @@ -291,7 +308,12 @@ where F: PrimeField + Ord, T: LoadedScalar, { - fn new(shifts: &[F], powers_of_x: &[T], x_3: &T, x_3_minus_x_shift_i: &BTreeMap) -> Self { + fn new( + shifts: &[(Rotation, T)], + powers_of_x: &[T], + x_3: &T, + x_3_minus_x_shift_i: &BTreeMap, + ) -> Self { let loader = x_3.loader(); let normalized_ell_primes = shifts .iter() @@ -301,9 +323,9 @@ where .iter() .enumerate() .filter(|&(i, _)| i != j) - .map(|(_, shift_i)| (*shift_j - shift_i)) + .map(|(_, shift_i)| (shift_j.1.clone() - &shift_i.1)) .reduce(|acc, value| acc * value) - .unwrap_or(F::ONE) + .unwrap_or_else(|| loader.load_const(&F::ONE)) }) .collect_vec(); @@ -313,17 +335,15 @@ where let barycentric_weights = shifts .iter() .zip(normalized_ell_primes.iter()) - .map(|(shift, normalized_ell_prime)| { - loader.sum_products_with_coeff(&[ - (*normalized_ell_prime, x_pow_k_minus_one, x_3), - (-(*normalized_ell_prime * shift), x_pow_k_minus_one, x), - ]) + .map(|((_, loaded_shift), normalized_ell_prime)| { + let tmp = normalized_ell_prime.clone() * x_pow_k_minus_one; + loader.sum_products(&[(&tmp, x_3), (&-(tmp.clone() * loaded_shift), x)]) }) .map(Fraction::one_over) .collect_vec(); let f_eval_coeff = Fraction::one_over(loader.product( - &shifts.iter().map(|shift| x_3_minus_x_shift_i.get(shift).unwrap()).collect_vec(), + &shifts.iter().map(|(shift, _)| x_3_minus_x_shift_i.get(shift).unwrap()).collect_vec(), )); Self { diff --git a/snark-verifier/src/pcs/kzg/multiopen/bdfg21.rs b/snark-verifier/src/pcs/kzg/multiopen/bdfg21.rs index d1398ebb..e13e09cc 100644 --- a/snark-verifier/src/pcs/kzg/multiopen/bdfg21.rs +++ b/snark-verifier/src/pcs/kzg/multiopen/bdfg21.rs @@ -6,7 +6,7 @@ use crate::{ PolynomialCommitmentScheme, Query, }, util::{ - arithmetic::{CurveAffine, Fraction, MultiMillerLoop, PrimeField}, + arithmetic::{CurveAffine, Fraction, MultiMillerLoop, PrimeField, Rotation}, msm::Msm, transcript::TranscriptRead, Itertools, @@ -37,7 +37,7 @@ where fn read_proof( _: &KzgSuccinctVerifyingKey, - _: &[Query], + _: &[Query], transcript: &mut T, ) -> Result, Error> where @@ -50,7 +50,7 @@ where svk: &KzgSuccinctVerifyingKey, commitments: &[Msm], z: &L::LoadedScalar, - queries: &[Query], + queries: &[Query], proof: &Bdfg21Proof, ) -> Result { let sets = query_sets(queries); @@ -106,24 +106,29 @@ where } } -fn query_sets(queries: &[Query]) -> Vec> { +fn query_sets(queries: &[Query]) -> Vec> { let poly_shifts = - queries.iter().fold(Vec::<(usize, Vec, Vec<&T>)>::new(), |mut poly_shifts, query| { + queries.iter().fold(Vec::<(usize, Vec<_>, Vec<&T>)>::new(), |mut poly_shifts, query| { if let Some(pos) = poly_shifts.iter().position(|(poly, _, _)| *poly == query.poly) { let (_, shifts, evals) = &mut poly_shifts[pos]; - if !shifts.contains(&query.shift) { - shifts.push(query.shift); + if !shifts.iter().map(|(shift, _)| shift).contains(&query.shift) { + shifts.push((query.shift, query.loaded_shift.clone())); evals.push(&query.eval); } } else { - poly_shifts.push((query.poly, vec![query.shift], vec![&query.eval])); + poly_shifts.push(( + query.poly, + vec![(query.shift, query.loaded_shift.clone())], + vec![&query.eval], + )); } poly_shifts }); - poly_shifts.into_iter().fold(Vec::>::new(), |mut sets, (poly, shifts, evals)| { + poly_shifts.into_iter().fold(Vec::>::new(), |mut sets, (poly, shifts, evals)| { if let Some(pos) = sets.iter().position(|set| { - BTreeSet::from_iter(set.shifts.iter()) == BTreeSet::from_iter(shifts.iter()) + BTreeSet::from_iter(set.shifts.iter().map(|(shift, _)| shift)) + == BTreeSet::from_iter(shifts.iter().map(|(shift, _)| shift)) }) { let set = &mut sets[pos]; if !set.polys.contains(&poly) { @@ -132,7 +137,7 @@ fn query_sets(queries: &[Query]) -> Vec(queries: &[Query]) -> Vec>( - sets: &[QuerySet], + sets: &[QuerySet], z: &T, z_prime: &T, ) -> Vec> { - let loader = z.loader(); - - let superset = sets.iter().flat_map(|set| set.shifts.clone()).sorted().dedup(); + // map of shift => loaded_shift, removing duplicate `shift` values + // shift is the rotation, not omega^rotation, to ensure BTreeMap does not depend on omega (otherwise ordering can change) + let superset = BTreeMap::from_iter(sets.iter().flat_map(|set| set.shifts.clone())); let size = sets.iter().map(|set| set.shifts.len()).chain(Some(2)).max().unwrap(); let powers_of_z = z.powers(size); let z_prime_minus_z_shift_i = BTreeMap::from_iter( - superset.map(|shift| (shift, z_prime.clone() - z.clone() * loader.load_const(&shift))), + superset + .into_iter() + .map(|(shift, loaded_shift)| (shift, z_prime.clone() - z.clone() * loaded_shift)), ); let mut z_s_1 = None; @@ -187,19 +194,22 @@ fn query_set_coeffs>( } #[derive(Clone, Debug)] -struct QuerySet<'a, F, T> { - shifts: Vec, +struct QuerySet<'a, S, T> { + shifts: Vec<(S, T)>, // vec of (shift, loaded_shift) polys: Vec, evals: Vec>, } -impl<'a, F: PrimeField, T: LoadedScalar> QuerySet<'a, F, T> { +impl<'a, S, T> QuerySet<'a, S, T> { fn msm>( &self, - coeff: &QuerySetCoeff, + coeff: &QuerySetCoeff, commitments: &[Msm<'a, C, L>], powers_of_mu: &[T], - ) -> Msm { + ) -> Msm + where + T: LoadedScalar, + { self.polys .iter() .zip(self.evals.iter()) @@ -242,10 +252,10 @@ where T: LoadedScalar, { fn new( - shifts: &[F], + shifts: &[(Rotation, T)], powers_of_z: &[T], z_prime: &T, - z_prime_minus_z_shift_i: &BTreeMap, + z_prime_minus_z_shift_i: &BTreeMap, z_s_1: &Option, ) -> Self { let loader = z_prime.loader(); @@ -258,9 +268,9 @@ where .iter() .enumerate() .filter(|&(i, _)| i != j) - .map(|(_, shift_i)| (*shift_j - shift_i)) + .map(|(_, shift_i)| (shift_j.1.clone() - &shift_i.1)) .reduce(|acc, value| acc * value) - .unwrap_or(F::ONE) + .unwrap_or_else(|| loader.load_const(&F::ONE)) }) .collect_vec(); @@ -270,17 +280,18 @@ where let barycentric_weights = shifts .iter() .zip(normalized_ell_primes.iter()) - .map(|(shift, normalized_ell_prime)| { - loader.sum_products_with_coeff(&[ - (*normalized_ell_prime, z_pow_k_minus_one, z_prime), - (-(*normalized_ell_prime * shift), z_pow_k_minus_one, z), - ]) + .map(|((_, loaded_shift), normalized_ell_prime)| { + let tmp = normalized_ell_prime.clone() * z_pow_k_minus_one; + loader.sum_products(&[(&tmp, z_prime), (&-(tmp.clone() * loaded_shift), z)]) }) .map(Fraction::one_over) .collect_vec(); let z_s = loader.product( - &shifts.iter().map(|shift| z_prime_minus_z_shift_i.get(shift).unwrap()).collect_vec(), + &shifts + .iter() + .map(|(shift, _)| z_prime_minus_z_shift_i.get(shift).unwrap()) + .collect_vec(), ); let z_s_1_over_z_s = z_s_1.clone().map(|z_s_1| Fraction::new(z_s_1, z_s.clone())); @@ -330,9 +341,9 @@ impl CostEstimation for KzgAs where M: MultiMillerLoop, { - type Input = Vec>; + type Input = Vec>; - fn estimate_cost(_: &Vec>) -> Cost { + fn estimate_cost(_: &Vec>) -> Cost { Cost { num_commitment: 2, num_msm: 2, ..Default::default() } } } diff --git a/snark-verifier/src/pcs/kzg/multiopen/gwc19.rs b/snark-verifier/src/pcs/kzg/multiopen/gwc19.rs index da5d51a6..e8114d09 100644 --- a/snark-verifier/src/pcs/kzg/multiopen/gwc19.rs +++ b/snark-verifier/src/pcs/kzg/multiopen/gwc19.rs @@ -6,7 +6,7 @@ use crate::{ PolynomialCommitmentScheme, Query, }, util::{ - arithmetic::{CurveAffine, MultiMillerLoop, PrimeField}, + arithmetic::{CurveAffine, MultiMillerLoop, Rotation}, msm::Msm, transcript::TranscriptRead, Itertools, @@ -32,7 +32,7 @@ where fn read_proof( _: &Self::VerifyingKey, - queries: &[Query], + queries: &[Query], transcript: &mut T, ) -> Result where @@ -45,7 +45,7 @@ where svk: &Self::VerifyingKey, commitments: &[Msm], z: &L::LoadedScalar, - queries: &[Query], + queries: &[Query], proof: &Self::Proof, ) -> Result { let sets = query_sets(queries); @@ -58,7 +58,10 @@ where .map(|(msm, power_of_u)| msm * power_of_u) .sum::>() }; - let z_omegas = sets.iter().map(|set| z.loader().load_const(&set.shift) * z); + let z_omegas = sets.iter().map(|set| { + let loaded_shift = set.loaded_shift.clone(); + loaded_shift * z + }); let rhs = proof .ws @@ -92,7 +95,7 @@ where C: CurveAffine, L: Loader, { - fn read(queries: &[Query], transcript: &mut T) -> Result + fn read(queries: &[Query], transcript: &mut T) -> Result where T: TranscriptRead, { @@ -103,22 +106,25 @@ where } } -struct QuerySet<'a, F, T> { - shift: F, +struct QuerySet<'a, S, T> { + shift: S, + loaded_shift: T, polys: Vec, evals: Vec<&'a T>, } -impl<'a, F, T> QuerySet<'a, F, T> +impl<'a, S, T> QuerySet<'a, S, T> where - F: PrimeField, T: Clone, { fn msm>( &self, commitments: &[Msm<'a, C, L>], powers_of_v: &[L::LoadedScalar], - ) -> Msm { + ) -> Msm + where + T: LoadedScalar, + { self.polys .iter() .zip(self.evals.iter().cloned()) @@ -132,9 +138,9 @@ where } } -fn query_sets(queries: &[Query]) -> Vec> +fn query_sets(queries: &[Query]) -> Vec> where - F: PrimeField, + S: PartialEq + Copy, T: Clone + PartialEq, { queries.iter().fold(Vec::new(), |mut sets, query| { @@ -144,6 +150,7 @@ where } else { sets.push(QuerySet { shift: query.shift, + loaded_shift: query.loaded_shift.clone(), polys: vec![query.poly], evals: vec![&query.eval], }); @@ -156,9 +163,9 @@ impl CostEstimation for KzgAs where M: MultiMillerLoop, { - type Input = Vec>; + type Input = Vec>; - fn estimate_cost(queries: &Vec>) -> Cost { + fn estimate_cost(queries: &Vec>) -> Cost { let num_w = query_sets(queries).len(); Cost { num_commitment: num_w, num_msm: num_w, ..Default::default() } } diff --git a/snark-verifier/src/system/halo2.rs b/snark-verifier/src/system/halo2.rs index 2dc5751d..74824361 100644 --- a/snark-verifier/src/system/halo2.rs +++ b/snark-verifier/src/system/halo2.rs @@ -141,6 +141,7 @@ pub fn compile<'a, C: CurveAffine, P: Params<'a, C>>( PlonkProtocol { domain, + domain_as_witness: None, preprocessed, num_instance: polynomials.num_instance(), num_witness: polynomials.num_witness(), diff --git a/snark-verifier/src/verifier/plonk.rs b/snark-verifier/src/verifier/plonk.rs index d5937ab8..9c910400 100644 --- a/snark-verifier/src/verifier/plonk.rs +++ b/snark-verifier/src/verifier/plonk.rs @@ -15,7 +15,10 @@ use crate::{ AccumulationDecider, AccumulationScheme, AccumulatorEncoding, PolynomialCommitmentScheme, Query, }, - util::{arithmetic::CurveAffine, transcript::TranscriptRead}, + util::{ + arithmetic::{CurveAffine, Rotation}, + transcript::TranscriptRead, + }, verifier::{plonk::protocol::CommonPolynomialEvaluation, SnarkVerifier}, Error, }; @@ -62,8 +65,12 @@ where proof: &Self::Proof, ) -> Result { let common_poly_eval = { - let mut common_poly_eval = - CommonPolynomialEvaluation::new(&protocol.domain, protocol.langranges(), &proof.z); + let mut common_poly_eval = CommonPolynomialEvaluation::new( + &protocol.domain, + protocol.langranges(), + &proof.z, + &protocol.domain_as_witness, + ); L::batch_invert(common_poly_eval.denoms()); common_poly_eval.evaluate(); @@ -140,7 +147,7 @@ where L: Loader, AS: AccumulationScheme + PolynomialCommitmentScheme - + CostEstimation>>, + + CostEstimation>>, { type Input = PlonkProtocol; @@ -168,7 +175,7 @@ where L: Loader, AS: AccumulationScheme + PolynomialCommitmentScheme - + CostEstimation>>, + + CostEstimation>>, { type Input = PlonkProtocol; diff --git a/snark-verifier/src/verifier/plonk/proof.rs b/snark-verifier/src/verifier/plonk/proof.rs index a42a56ae..459027ba 100644 --- a/snark-verifier/src/verifier/plonk/proof.rs +++ b/snark-verifier/src/verifier/plonk/proof.rs @@ -13,7 +13,10 @@ use crate::{ }, Error, }; -use std::{collections::HashMap, iter}; +use std::{ + collections::{BTreeMap, HashMap}, + iter, +}; /// Proof of PLONK with [`PolynomialCommitmentScheme`] that has /// [`AccumulationScheme`]. @@ -153,26 +156,42 @@ where } /// Empty queries - pub fn empty_queries(protocol: &PlonkProtocol) -> Vec> { - protocol - .queries - .iter() - .map(|query| { - let shift = protocol.domain.rotate_scalar(C::Scalar::ONE, query.rotation); - pcs::Query::new(query.poly, shift) - }) - .collect() + pub fn empty_queries(protocol: &PlonkProtocol) -> Vec> { + // `preprocessed` should always be non-empty, unless the circuit has no constraints or constants + protocol.queries.iter().map(|query| pcs::Query::new(query.poly, query.rotation)).collect() } pub(super) fn queries( &self, protocol: &PlonkProtocol, mut evaluations: HashMap, - ) -> Vec> { + ) -> Vec> { + if protocol.queries.is_empty() { + return vec![]; + } + let loader = evaluations[&protocol.queries[0]].loader(); + let rotations = + protocol.queries.iter().map(|query| query.rotation).sorted().dedup().collect_vec(); + let loaded_shifts = if let Some(domain) = protocol.domain_as_witness.as_ref() { + // the `rotation`s are still constants, it is only generator `omega` that might be witness + BTreeMap::from_iter( + rotations.into_iter().map(|rotation| (rotation, domain.rotate_one(rotation))), + ) + } else { + BTreeMap::from_iter(rotations.into_iter().map(|rotation| { + ( + rotation, + loader.load_const(&protocol.domain.rotate_scalar(C::Scalar::ONE, rotation)), + ) + })) + }; Self::empty_queries(protocol) .into_iter() .zip(protocol.queries.iter().map(|query| evaluations.remove(query).unwrap())) - .map(|(query, eval)| query.with_evaluation(eval)) + .map(|(query, eval)| { + let shift = loaded_shifts[&query.shift].clone(); + query.with_evaluation(shift, eval) + }) .collect() } diff --git a/snark-verifier/src/verifier/plonk/protocol.rs b/snark-verifier/src/verifier/plonk/protocol.rs index 97f6f336..098e7de9 100644 --- a/snark-verifier/src/verifier/plonk/protocol.rs +++ b/snark-verifier/src/verifier/plonk/protocol.rs @@ -1,7 +1,7 @@ use crate::{ loader::{native::NativeLoader, LoadedScalar, Loader}, util::{ - arithmetic::{CurveAffine, Domain, Field, Fraction, Rotation}, + arithmetic::{CurveAffine, Domain, Field, Fraction, PrimeField, Rotation}, Itertools, }, }; @@ -9,13 +9,44 @@ use num_integer::Integer; use num_traits::One; use serde::{Deserialize, Serialize}; use std::{ - cmp::max, + cmp::{max, Ordering}, collections::{BTreeMap, BTreeSet}, fmt::Debug, iter::{self, Sum}, ops::{Add, Mul, Neg, Sub}, }; +/// Domain parameters to be optionally loaded as witnesses +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct DomainAsWitness +where + C: CurveAffine, + L: Loader, +{ + /// Number of rows in the domain + pub n: L::LoadedScalar, + /// Generator of the domain + pub gen: L::LoadedScalar, + /// Inverse generator of the domain + pub gen_inv: L::LoadedScalar, +} + +impl DomainAsWitness +where + C: CurveAffine, + L: Loader, +{ + /// Rotate `F::one()` to given `rotation`. + pub fn rotate_one(&self, rotation: Rotation) -> L::LoadedScalar { + let loader = self.gen.loader(); + match rotation.0.cmp(&0) { + Ordering::Equal => loader.load_one(), + Ordering::Greater => self.gen.pow_const(rotation.0 as u64), + Ordering::Less => self.gen_inv.pow_const(-rotation.0 as u64), + } + } +} + /// Protocol specifying configuration of a PLONK. #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PlonkProtocol @@ -29,6 +60,15 @@ where ))] /// Working domain. pub domain: Domain, + + #[serde(bound( + serialize = "L::LoadedScalar: Serialize", + deserialize = "L::LoadedScalar: Deserialize<'de>" + ))] + #[serde(skip_serializing_if = "Option::is_none")] + /// Optional: load `domain.n` and `domain.gen` as a witness + pub domain_as_witness: Option>, + #[serde(bound( serialize = "L::LoadedEcPoint: Serialize", deserialize = "L::LoadedEcPoint: Deserialize<'de>" @@ -115,6 +155,7 @@ where .map(|transcript_initial_state| loader.load_const(transcript_initial_state)); PlonkProtocol { domain: self.domain.clone(), + domain_as_witness: None, preprocessed, num_instance: self.num_instance.clone(), num_witness: self.num_witness.clone(), @@ -133,12 +174,17 @@ where #[cfg(feature = "loader_halo2")] mod halo2 { use crate::{ - loader::halo2::{EccInstructions, Halo2Loader}, + loader::{ + halo2::{EccInstructions, Halo2Loader}, + LoadedScalar, + }, util::arithmetic::CurveAffine, verifier::plonk::PlonkProtocol, }; use std::rc::Rc; + use super::DomainAsWitness; + impl PlonkProtocol where C: CurveAffine, @@ -149,7 +195,15 @@ mod halo2 { pub fn loaded_preprocessed_as_witness>( &self, loader: &Rc>, + load_n_as_witness: bool, ) -> PlonkProtocol>> { + let domain_as_witness = load_n_as_witness.then(|| { + let n = loader.assign_scalar(C::Scalar::from(self.domain.n as u64)); + let gen = loader.assign_scalar(self.domain.gen); + let gen_inv = gen.invert().expect("subgroup generation is invertible"); + DomainAsWitness { n, gen, gen_inv } + }); + let preprocessed = self .preprocessed .iter() @@ -161,6 +215,7 @@ mod halo2 { .map(|transcript_initial_state| loader.assign_scalar(*transcript_initial_state)); PlonkProtocol { domain: self.domain.clone(), + domain_as_witness, preprocessed, num_instance: self.num_instance.clone(), num_witness: self.num_witness.clone(), @@ -201,26 +256,39 @@ where C: CurveAffine, L: Loader, { + // if `n_as_witness` is Some, then we assume `n_as_witness` has value equal to `domain.n` (i.e., number of rows in the circuit) + // and is loaded as a witness instead of a constant. + // The generator of `domain` also depends on `n`. pub fn new( domain: &Domain, - langranges: impl IntoIterator, + lagranges: impl IntoIterator, z: &L::LoadedScalar, + domain_as_witness: &Option>, ) -> Self { let loader = z.loader(); - let zn = z.pow_const(domain.n as u64); - let langranges = langranges.into_iter().sorted().dedup().collect_vec(); - + let lagranges = lagranges.into_iter().sorted().dedup().collect_vec(); let one = loader.load_one(); + + let (zn, n_inv, omegas) = if let Some(domain) = domain_as_witness.as_ref() { + let zn = z.pow_var(&domain.n, C::Scalar::S as usize + 1); + let n_inv = domain.n.invert().expect("n is not zero"); + let omegas = lagranges.iter().map(|&i| domain.rotate_one(Rotation(i))).collect_vec(); + (zn, n_inv, omegas) + } else { + let zn = z.pow_const(domain.n as u64); + let n_inv = loader.load_const(&domain.n_inv); + let omegas = lagranges + .iter() + .map(|&i| loader.load_const(&domain.rotate_scalar(C::Scalar::ONE, Rotation(i)))) + .collect_vec(); + (zn, n_inv, omegas) + }; + let zn_minus_one = zn.clone() - &one; let zn_minus_one_inv = Fraction::one_over(zn_minus_one.clone()); - let n_inv = loader.load_const(&domain.n_inv); let numer = zn_minus_one.clone() * &n_inv; - let omegas = langranges - .iter() - .map(|&i| loader.load_const(&domain.rotate_scalar(C::Scalar::ONE, Rotation(i)))) - .collect_vec(); let lagrange_evals = omegas .iter() .map(|omega| Fraction::new(numer.clone() * omega, z.clone() - omega)) @@ -231,7 +299,7 @@ where zn_minus_one, zn_minus_one_inv, identity: z.clone(), - lagrange: langranges.into_iter().zip(lagrange_evals).collect(), + lagrange: lagranges.into_iter().zip(lagrange_evals).collect(), } } From 9d981455c04717e7338cf3a17b19e016121608c5 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Fri, 18 Aug 2023 10:18:30 -0700 Subject: [PATCH 08/19] chore: derive Default for VerifierUniversality --- snark-verifier-sdk/src/halo2/aggregation.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/snark-verifier-sdk/src/halo2/aggregation.rs b/snark-verifier-sdk/src/halo2/aggregation.rs index 0063a599..60674a6c 100644 --- a/snark-verifier-sdk/src/halo2/aggregation.rs +++ b/snark-verifier-sdk/src/halo2/aggregation.rs @@ -54,9 +54,10 @@ pub struct SnarkAggregationWitness<'a> { } /// Different possible stages of universality the aggregation circuit can support -#[derive(PartialEq, Eq, Clone, Copy, Debug)] +#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)] pub enum VerifierUniversality { /// Default: verifier is specific to a single circuit + #[default] None, /// Preprocessed digest (commitments to fixed columns) is loaded as witness PreprocessedAsWitness, From f309edea16ed483cf828dd843fabb1b02aabc65a Mon Sep 17 00:00:00 2001 From: Han Date: Fri, 2 Jun 2023 14:41:37 +0800 Subject: [PATCH 09/19] feat: upgrade `revm` to support lastest hardfork (#40) --- .github/workflows/ci.yaml | 2 +- rust-toolchain | 2 +- snark-verifier-sdk/src/evm.rs | 17 +- snark-verifier/Cargo.toml | 9 +- .../examples/evm-verifier-with-accumulator.rs | 16 +- snark-verifier/examples/evm-verifier.rs | 16 +- snark-verifier/src/loader/evm.rs | 10 +- snark-verifier/src/loader/evm/loader.rs | 44 +- snark-verifier/src/loader/evm/test.rs | 48 - snark-verifier/src/loader/evm/test/tui.rs | 896 ------------------ snark-verifier/src/loader/evm/util.rs | 13 +- .../src/loader/evm/util/executor.rs | 854 +---------------- snark-verifier/src/pcs/kzg/decider.rs | 8 +- .../src/system/halo2/transcript/evm.rs | 4 +- snark-verifier/src/util/arithmetic.rs | 2 +- snark-verifier/src/util/poly.rs | 10 +- 16 files changed, 97 insertions(+), 1854 deletions(-) delete mode 100644 snark-verifier/src/loader/evm/test.rs delete mode 100644 snark-verifier/src/loader/evm/test/tui.rs diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index e057f89d..7261444e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -24,7 +24,7 @@ jobs: cache-on-failure: true - name: Install solc - run: (hash svm 2>/dev/null || cargo install svm-rs) && svm install 0.8.17 && solc --version + run: (hash svm 2>/dev/null || cargo install --version 0.2.23 svm-rs) && svm install 0.8.20 && solc --version - name: Run test run: cargo test --all -- --nocapture diff --git a/rust-toolchain b/rust-toolchain index ee2d639b..6f6d7b39 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -nightly-2023-08-12 \ No newline at end of file +nightly-2023-08-12 diff --git a/snark-verifier-sdk/src/evm.rs b/snark-verifier-sdk/src/evm.rs index f423d327..97b1b96e 100644 --- a/snark-verifier-sdk/src/evm.rs +++ b/snark-verifier-sdk/src/evm.rs @@ -3,7 +3,6 @@ use crate::{GWC, SHPLONK}; use super::{CircuitExt, PlonkVerifier}; #[cfg(feature = "display")] use ark_std::{end_timer, start_timer}; -use ethereum_types::Address; use halo2_base::halo2_proofs::{ halo2curves::bn256::{Bn256, Fq, Fr, G1Affine}, plonk::{create_proof, verify_proof, Circuit, ProvingKey, VerifyingKey}, @@ -23,7 +22,7 @@ use itertools::Itertools; use rand::{rngs::StdRng, SeedableRng}; pub use snark_verifier::loader::evm::encode_calldata; use snark_verifier::{ - loader::evm::{compile_yul, EvmLoader, ExecutorBuilder}, + loader::evm::{compile_yul, deploy_and_call, EvmLoader}, pcs::{ kzg::{KzgAccumulator, KzgAsVerifyingKey, KzgDecidingKey, KzgSuccinctVerifyingKey}, AccumulationDecider, AccumulationScheme, PolynomialCommitmentScheme, @@ -177,18 +176,8 @@ pub fn gen_evm_verifier_shplonk>( pub fn evm_verify(deployment_code: Vec, instances: Vec>, proof: Vec) { let calldata = encode_calldata(&instances, &proof); - let success = { - let mut evm = ExecutorBuilder::default().with_gas_limit(u64::MAX.into()).build(); - - let caller = Address::from_low_u64_be(0xfe); - let verifier = evm.deploy(caller, deployment_code.into(), 0.into()).address.unwrap(); - let result = evm.call_raw(caller, verifier, calldata.into(), 0.into()); - - dbg!(result.gas_used); - - !result.reverted - }; - assert!(success); + let gas_cost = deploy_and_call(deployment_code, calldata).unwrap(); + dbg!(gas_cost); } pub fn write_calldata(instances: &[Vec], proof: &[u8], path: &Path) -> io::Result { diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index ebbf283b..f4c4f4af 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -25,11 +25,8 @@ poseidon-rs = { git = "https://github.com/axiom-crypto/poseidon-circuit.git", re rayon = { version = "1.7", optional = true } # loader_evm -sha3 = { version = "0.10.8", optional = true } -bytes = { version = "1.4.0", default-features = false, optional = true } -primitive-types = { version = "0.12.1", default-features = false, features = ["std"], optional = true } -rlp = { version = "0.5.2", default-features = false, features = ["std"], optional = true } -revm = { version = "2.3.1", optional = true } +sha3 = { version = "0.10", optional = true } +revm = { version = "3.3.0", optional = true } # loader_halo2 halo2-ecc = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false, optional = true } @@ -47,7 +44,7 @@ tui = { version = "0.19", default-features = false, features = ["crossterm"] } [features] default = ["loader_evm", "loader_halo2", "halo2-axiom", "display"] display = ["halo2-base/display", "halo2-ecc?/display"] -loader_evm = ["dep:primitive-types", "dep:sha3", "dep:revm", "dep:bytes", "dep:rlp"] +loader_evm = ["dep:sha3", "dep:revm"] loader_halo2 = ["halo2-ecc"] parallel = ["dep:rayon"] # EXACTLY one of halo2-pse / halo2-axiom should always be turned on; not sure how to enforce this with Cargo diff --git a/snark-verifier/examples/evm-verifier-with-accumulator.rs b/snark-verifier/examples/evm-verifier-with-accumulator.rs index 41493efa..650598aa 100644 --- a/snark-verifier/examples/evm-verifier-with-accumulator.rs +++ b/snark-verifier/examples/evm-verifier-with-accumulator.rs @@ -23,7 +23,7 @@ use itertools::Itertools; use rand::rngs::OsRng; use snark_verifier::{ loader::{ - evm::{self, encode_calldata, Address, EvmLoader, ExecutorBuilder}, + evm::{self, deploy_and_call, encode_calldata, EvmLoader}, native::NativeLoader, }, pcs::kzg::{Gwc19, KzgAs, LimbsEncoding}, @@ -559,18 +559,8 @@ fn gen_aggregation_evm_verifier( fn evm_verify(deployment_code: Vec, instances: Vec>, proof: Vec) { let calldata = encode_calldata(&instances, &proof); - let success = { - let mut evm = ExecutorBuilder::default().with_gas_limit(u64::MAX.into()).build(); - - let caller = Address::from_low_u64_be(0xfe); - let verifier = evm.deploy(caller, deployment_code.into(), 0.into()).address.unwrap(); - let result = evm.call_raw(caller, verifier, calldata.into(), 0.into()); - - dbg!(result.gas_used); - - !result.reverted - }; - assert!(success); + let gas_cost = deploy_and_call(deployment_code, calldata).unwrap(); + dbg!(gas_cost); } fn main() { diff --git a/snark-verifier/examples/evm-verifier.rs b/snark-verifier/examples/evm-verifier.rs index 5b2aa802..c7f206b1 100644 --- a/snark-verifier/examples/evm-verifier.rs +++ b/snark-verifier/examples/evm-verifier.rs @@ -21,7 +21,7 @@ use halo2_proofs::{ use itertools::Itertools; use rand::{rngs::OsRng, RngCore}; use snark_verifier::{ - loader::evm::{self, encode_calldata, Address, EvmLoader, ExecutorBuilder}, + loader::evm::{self, deploy_and_call, encode_calldata, EvmLoader}, pcs::kzg::{Gwc19, KzgAs}, system::halo2::{compile, transcript::evm::EvmTranscript, Config}, verifier::{self, SnarkVerifier}, @@ -242,18 +242,8 @@ fn gen_evm_verifier( fn evm_verify(deployment_code: Vec, instances: Vec>, proof: Vec) { let calldata = encode_calldata(&instances, &proof); - let success = { - let mut evm = ExecutorBuilder::default().with_gas_limit(u64::MAX.into()).build(); - - let caller = Address::from_low_u64_be(0xfe); - let verifier = evm.deploy(caller, deployment_code.into(), 0.into()).address.unwrap(); - let result = evm.call_raw(caller, verifier, calldata.into(), 0.into()); - - dbg!(result.gas_used); - - !result.reverted - }; - assert!(success); + let gas_cost = deploy_and_call(deployment_code, calldata).unwrap(); + dbg!(gas_cost); } fn main() { diff --git a/snark-verifier/src/loader/evm.rs b/snark-verifier/src/loader/evm.rs index e942b4a3..74ed0f4e 100644 --- a/snark-verifier/src/loader/evm.rs +++ b/snark-verifier/src/loader/evm.rs @@ -4,14 +4,8 @@ mod code; pub(crate) mod loader; pub(crate) mod util; -#[cfg(test)] -mod test; - pub use loader::{EcPoint, EvmLoader, Scalar}; pub use util::{ - compile_yul, encode_calldata, estimate_gas, fe_to_u256, modulus, u256_to_fe, Address, - ExecutorBuilder, H256, U256, U512, + compile_yul, deploy_and_call, encode_calldata, estimate_gas, fe_to_u256, modulus, u256_to_fe, + Address, B256, U256, U512, }; - -#[cfg(test)] -pub use test::execute; diff --git a/snark-verifier/src/loader/evm/loader.rs b/snark-verifier/src/loader/evm/loader.rs index ba304f2b..127cc7e4 100644 --- a/snark-verifier/src/loader/evm/loader.rs +++ b/snark-verifier/src/loader/evm/loader.rs @@ -55,14 +55,10 @@ pub struct EvmLoader { code: RefCell, ptr: RefCell, cache: RefCell>, - #[cfg(test)] - gas_metering_ids: RefCell>, } fn hex_encode_u256(value: &U256) -> String { - let mut bytes = [0; 32]; - value.to_big_endian(&mut bytes); - format!("0x{}", hex::encode(bytes)) + format!("0x{}", hex::encode(value.to_be_bytes::<32>())) } impl EvmLoader { @@ -82,8 +78,6 @@ impl EvmLoader { code: RefCell::new(code), ptr: Default::default(), cache: Default::default(), - #[cfg(test)] - gas_metering_ids: RefCell::new(Vec::new()), }) } @@ -308,11 +302,11 @@ impl EvmLoader { fn invert(self: &Rc, scalar: &Scalar) -> Scalar { let rd_ptr = self.allocate(0x20); let [cd_ptr, ..] = [ - &self.scalar(Value::Constant(0x20.into())), - &self.scalar(Value::Constant(0x20.into())), - &self.scalar(Value::Constant(0x20.into())), + &self.scalar(Value::Constant(U256::from(0x20))), + &self.scalar(Value::Constant(U256::from(0x20))), + &self.scalar(Value::Constant(U256::from(0x20))), scalar, - &self.scalar(Value::Constant(self.scalar_modulus - 2)), + &self.scalar(Value::Constant(self.scalar_modulus - U256::from(2))), &self.scalar(Value::Constant(self.scalar_modulus)), ] .map(|value| self.dup_scalar(value).ptr()); @@ -383,8 +377,8 @@ impl EvmLoader { fn add(self: &Rc, lhs: &Scalar, rhs: &Scalar) -> Scalar { if let (Value::Constant(lhs), Value::Constant(rhs)) = (&lhs.value, &rhs.value) { - let out = (U512::from(lhs) + U512::from(rhs)) % U512::from(self.scalar_modulus); - return self.scalar(Value::Constant(out.try_into().unwrap())); + let out = (U512::from(*lhs) + U512::from(*rhs)) % U512::from(self.scalar_modulus); + return self.scalar(Value::Constant(U256::from(out))); } self.scalar(Value::Sum(Box::new(lhs.value.clone()), Box::new(rhs.value.clone()))) @@ -403,8 +397,8 @@ impl EvmLoader { fn mul(self: &Rc, lhs: &Scalar, rhs: &Scalar) -> Scalar { if let (Value::Constant(lhs), Value::Constant(rhs)) = (&lhs.value, &rhs.value) { - let out = (U512::from(lhs) * U512::from(rhs)) % U512::from(self.scalar_modulus); - return self.scalar(Value::Constant(out.try_into().unwrap())); + let out = (U512::from(*lhs) * U512::from(*rhs)) % U512::from(self.scalar_modulus); + return self.scalar(Value::Constant(U256::from(out))); } self.scalar(Value::Product(Box::new(lhs.value.clone()), Box::new(rhs.value.clone()))) @@ -421,22 +415,16 @@ impl EvmLoader { #[cfg(test)] impl EvmLoader { - fn start_gas_metering(self: &Rc, identifier: &str) { - self.gas_metering_ids.borrow_mut().push(identifier.to_string()); - let code = format!("let {identifier} := gas()"); - self.code.borrow_mut().runtime_append(code); + fn start_gas_metering(self: &Rc, _: &str) { + // unimplemented } fn end_gas_metering(self: &Rc) { - let code = - format!("log1(0, 0, sub({}, gas()))", self.gas_metering_ids.borrow().last().unwrap()); - self.code.borrow_mut().runtime_append(code); + // unimplemented } - pub fn print_gas_metering(self: &Rc, costs: Vec) { - for (identifier, cost) in self.gas_metering_ids.borrow().iter().zip(costs) { - println!("{identifier}: {cost}"); - } + pub fn print_gas_metering(self: &Rc, _: Vec) { + // unimplemented } } @@ -648,7 +636,7 @@ where fn ec_point_load_const(&self, value: &C) -> EcPoint { let coordinates = value.coordinates().unwrap(); let [x, y] = [coordinates.x(), coordinates.y()] - .map(|coordinate| U256::from_little_endian(coordinate.to_repr().as_ref())); + .map(|coordinate| U256::try_from_le_slice(coordinate.to_repr().as_ref()).unwrap()); self.ec_point(Value::Constant((x, y))) } @@ -663,7 +651,7 @@ where .iter() .cloned() .map(|(scalar, ec_point)| match scalar.value { - Value::Constant(constant) if U256::one() == constant => ec_point.clone(), + Value::Constant(constant) if U256::from(1) == constant => ec_point.clone(), _ => ec_point.loader.ec_point_scalar_mul(ec_point, scalar), }) .reduce(|acc, ec_point| acc.loader.ec_point_add(&acc, &ec_point)) diff --git a/snark-verifier/src/loader/evm/test.rs b/snark-verifier/src/loader/evm/test.rs deleted file mode 100644 index e3467408..00000000 --- a/snark-verifier/src/loader/evm/test.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::{ - loader::evm::{test::tui::Tui, Address, ExecutorBuilder, U256}, - util::Itertools, -}; -use std::env::var_os; - -mod tui; - -fn debug() -> bool { - matches!( - var_os("DEBUG"), - Some(value) if value.to_str() == Some("1") - ) -} - -pub fn execute(deployment_code: Vec, calldata: Vec) -> (bool, u64, Vec) { - assert!( - deployment_code.len() <= 0x6000, - "Contract size {} exceeds the limit 24576", - deployment_code.len() - ); - - let debug = debug(); - let caller = Address::from_low_u64_be(0xfe); - - let mut evm = ExecutorBuilder::default() - .with_gas_limit(u64::MAX.into()) - .set_debugger(debug) - .build(); - - let contract = evm - .deploy(caller, deployment_code.into(), 0.into()) - .address - .unwrap(); - let result = evm.call_raw(caller, contract, calldata.into(), 0.into()); - - let costs = result - .logs - .into_iter() - .map(|log| U256::from_big_endian(log.topics[0].as_bytes()).as_u64()) - .collect_vec(); - - if debug { - Tui::new(result.debug.unwrap().flatten(0), 0).start(); - } - - (!result.reverted, result.gas_used, costs) -} diff --git a/snark-verifier/src/loader/evm/test/tui.rs b/snark-verifier/src/loader/evm/test/tui.rs deleted file mode 100644 index 9bd68bb9..00000000 --- a/snark-verifier/src/loader/evm/test/tui.rs +++ /dev/null @@ -1,896 +0,0 @@ -//! Copied and modified from https://github.com/foundry-rs/foundry/blob/master/ui/src/lib.rs - -use crate::loader::evm::{ - util::executor::{CallKind, DebugStep}, - Address, -}; -use crossterm::{ - event::{ - self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode, KeyEvent, KeyModifiers, - MouseEvent, MouseEventKind, - }, - execute, - terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, -}; -use revm::opcode; -use std::{ - cmp::{max, min}, - io, - sync::mpsc, - thread, - time::{Duration, Instant}, -}; -use tui::{ - backend::{Backend, CrosstermBackend}, - layout::{Alignment, Constraint, Direction, Layout, Rect}, - style::{Color, Modifier, Style}, - terminal::Frame, - text::{Span, Spans, Text}, - widgets::{Block, Borders, Paragraph, Wrap}, - Terminal, -}; - -pub struct Tui { - debug_arena: Vec<(Address, Vec, CallKind)>, - terminal: Terminal>, - key_buffer: String, - current_step: usize, -} - -impl Tui { - pub fn new(debug_arena: Vec<(Address, Vec, CallKind)>, current_step: usize) -> Self { - enable_raw_mode().unwrap(); - let mut stdout = io::stdout(); - execute!(stdout, EnterAlternateScreen, EnableMouseCapture).unwrap(); - let backend = CrosstermBackend::new(stdout); - let mut terminal = Terminal::new(backend).unwrap(); - terminal.hide_cursor().unwrap(); - Tui { debug_arena, terminal, key_buffer: String::new(), current_step } - } - - pub fn start(mut self) { - std::panic::set_hook(Box::new(|e| { - disable_raw_mode().expect("Unable to disable raw mode"); - execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture) - .expect("unable to execute disable mouse capture"); - println!("{e}"); - })); - let tick_rate = Duration::from_millis(60); - - let (tx, rx) = mpsc::channel(); - thread::spawn(move || { - let mut last_tick = Instant::now(); - loop { - if event::poll(tick_rate - last_tick.elapsed()).unwrap() { - let event = event::read().unwrap(); - if let Event::Key(key) = event { - if tx.send(Interrupt::KeyPressed(key)).is_err() { - return; - } - } else if let Event::Mouse(mouse) = event { - if tx.send(Interrupt::MouseEvent(mouse)).is_err() { - return; - } - } - } - if last_tick.elapsed() > tick_rate { - if tx.send(Interrupt::IntervalElapsed).is_err() { - return; - } - last_tick = Instant::now(); - } - } - }); - - self.terminal.clear().unwrap(); - let mut draw_memory: DrawMemory = DrawMemory::default(); - - let debug_call = &self.debug_arena; - let mut opcode_list: Vec = - debug_call[0].1.iter().map(|step| step.pretty_opcode()).collect(); - let mut last_index = 0; - - let mut stack_labels = false; - let mut mem_utf = false; - loop { - if last_index != draw_memory.inner_call_index { - opcode_list = debug_call[draw_memory.inner_call_index] - .1 - .iter() - .map(|step| step.pretty_opcode()) - .collect(); - last_index = draw_memory.inner_call_index; - } - match rx.recv().unwrap() { - Interrupt::KeyPressed(event) => match event.code { - KeyCode::Char('q') => { - disable_raw_mode().unwrap(); - execute!( - self.terminal.backend_mut(), - LeaveAlternateScreen, - DisableMouseCapture - ) - .unwrap(); - return; - } - KeyCode::Char('j') | KeyCode::Down => { - for _ in 0..Tui::buffer_as_number(&self.key_buffer, 1) { - if event.modifiers.contains(KeyModifiers::CONTROL) { - let max_mem = (debug_call[draw_memory.inner_call_index].1 - [self.current_step] - .memory - .len() - / 32) - .saturating_sub(1); - let step = if event.modifiers.contains(KeyModifiers::ALT) { - 20 - } else { - 1 - }; - if draw_memory.current_mem_startline + step < max_mem { - draw_memory.current_mem_startline += step; - } - } else if self.current_step < opcode_list.len() - 1 { - self.current_step += 1; - } else if draw_memory.inner_call_index < debug_call.len() - 1 { - draw_memory.inner_call_index += 1; - self.current_step = 0; - } - } - self.key_buffer.clear(); - } - KeyCode::Char('J') => { - for _ in 0..Tui::buffer_as_number(&self.key_buffer, 1) { - let max_stack = debug_call[draw_memory.inner_call_index].1 - [self.current_step] - .stack - .len() - .saturating_sub(1); - if draw_memory.current_stack_startline < max_stack { - draw_memory.current_stack_startline += 1; - } - } - self.key_buffer.clear(); - } - KeyCode::Char('k') | KeyCode::Up => { - for _ in 0..Tui::buffer_as_number(&self.key_buffer, 1) { - if event.modifiers.contains(KeyModifiers::CONTROL) { - draw_memory.current_mem_startline = - draw_memory.current_mem_startline.saturating_sub(1); - } else if self.current_step > 0 { - self.current_step -= 1; - } else if draw_memory.inner_call_index > 0 { - draw_memory.inner_call_index -= 1; - self.current_step = - debug_call[draw_memory.inner_call_index].1.len() - 1; - } - } - self.key_buffer.clear(); - } - KeyCode::Char('K') => { - for _ in 0..Tui::buffer_as_number(&self.key_buffer, 1) { - draw_memory.current_stack_startline = - draw_memory.current_stack_startline.saturating_sub(1); - } - self.key_buffer.clear(); - } - KeyCode::Char('g') => { - draw_memory.inner_call_index = 0; - self.current_step = 0; - self.key_buffer.clear(); - } - KeyCode::Char('G') => { - draw_memory.inner_call_index = debug_call.len() - 1; - self.current_step = debug_call[draw_memory.inner_call_index].1.len() - 1; - self.key_buffer.clear(); - } - KeyCode::Char('c') => { - draw_memory.inner_call_index = - draw_memory.inner_call_index.saturating_sub(1); - self.current_step = debug_call[draw_memory.inner_call_index].1.len() - 1; - self.key_buffer.clear(); - } - KeyCode::Char('C') => { - if debug_call.len() > draw_memory.inner_call_index + 1 { - draw_memory.inner_call_index += 1; - self.current_step = 0; - } - self.key_buffer.clear(); - } - KeyCode::Char('s') => { - for _ in 0..Tui::buffer_as_number(&self.key_buffer, 1) { - let remaining_ops = &opcode_list[self.current_step..]; - self.current_step += remaining_ops - .iter() - .enumerate() - .find_map(|(i, op)| { - if i < remaining_ops.len() - 1 { - match ( - op.contains("JUMP") && op != "JUMPDEST", - &*remaining_ops[i + 1], - ) { - (true, "JUMPDEST") => Some(i + 1), - _ => None, - } - } else { - None - } - }) - .unwrap_or(opcode_list.len() - 1); - if self.current_step > opcode_list.len() { - self.current_step = opcode_list.len() - 1 - }; - } - self.key_buffer.clear(); - } - KeyCode::Char('a') => { - for _ in 0..Tui::buffer_as_number(&self.key_buffer, 1) { - let prev_ops = &opcode_list[..self.current_step]; - self.current_step = prev_ops - .iter() - .enumerate() - .rev() - .find_map(|(i, op)| { - if i > 0 { - match ( - prev_ops[i - 1].contains("JUMP") - && prev_ops[i - 1] != "JUMPDEST", - &**op, - ) { - (true, "JUMPDEST") => Some(i - 1), - _ => None, - } - } else { - None - } - }) - .unwrap_or_default(); - } - self.key_buffer.clear(); - } - KeyCode::Char('t') => { - stack_labels = !stack_labels; - } - KeyCode::Char('m') => { - mem_utf = !mem_utf; - } - KeyCode::Char(other) => match other { - '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' => { - self.key_buffer.push(other); - } - _ => { - self.key_buffer.clear(); - } - }, - _ => { - self.key_buffer.clear(); - } - }, - Interrupt::MouseEvent(event) => match event.kind { - MouseEventKind::ScrollUp => { - if self.current_step > 0 { - self.current_step -= 1; - } else if draw_memory.inner_call_index > 0 { - draw_memory.inner_call_index -= 1; - draw_memory.current_mem_startline = 0; - draw_memory.current_stack_startline = 0; - self.current_step = - debug_call[draw_memory.inner_call_index].1.len() - 1; - } - } - MouseEventKind::ScrollDown => { - if self.current_step < opcode_list.len() - 1 { - self.current_step += 1; - } else if draw_memory.inner_call_index < debug_call.len() - 1 { - draw_memory.inner_call_index += 1; - draw_memory.current_mem_startline = 0; - draw_memory.current_stack_startline = 0; - self.current_step = 0; - } - } - _ => {} - }, - Interrupt::IntervalElapsed => {} - } - let current_step = self.current_step; - self.terminal - .draw(|f| { - Tui::draw_layout( - f, - debug_call[draw_memory.inner_call_index].0, - &debug_call[draw_memory.inner_call_index].1[..], - &opcode_list, - current_step, - &mut draw_memory, - stack_labels, - mem_utf, - ) - }) - .unwrap(); - } - } - - fn buffer_as_number(buffer: &str, default_value: usize) -> usize { - if let Ok(num) = buffer.parse() { - if num >= 1 { - num - } else { - default_value - } - } else { - default_value - } - } - - fn draw_layout( - f: &mut Frame, - address: Address, - debug_steps: &[DebugStep], - opcode_list: &[String], - current_step: usize, - draw_memory: &mut DrawMemory, - stack_labels: bool, - mem_utf: bool, - ) { - let total_size = f.size(); - if total_size.width < 225 { - Tui::vertical_layout( - f, - address, - debug_steps, - opcode_list, - current_step, - draw_memory, - stack_labels, - mem_utf, - ); - } else { - Tui::square_layout( - f, - address, - debug_steps, - opcode_list, - current_step, - draw_memory, - stack_labels, - mem_utf, - ); - } - } - - fn vertical_layout( - f: &mut Frame, - address: Address, - debug_steps: &[DebugStep], - opcode_list: &[String], - current_step: usize, - draw_memory: &mut DrawMemory, - stack_labels: bool, - mem_utf: bool, - ) { - let total_size = f.size(); - if let [app, footer] = Layout::default() - .direction(Direction::Vertical) - .constraints([Constraint::Ratio(98, 100), Constraint::Ratio(2, 100)].as_ref()) - .split(total_size)[..] - { - if let [op_pane, stack_pane, memory_pane] = Layout::default() - .direction(Direction::Vertical) - .constraints( - [Constraint::Ratio(1, 3), Constraint::Ratio(1, 3), Constraint::Ratio(1, 3)] - .as_ref(), - ) - .split(app)[..] - { - Tui::draw_footer(f, footer); - Tui::draw_op_list( - f, - address, - debug_steps, - opcode_list, - current_step, - draw_memory, - op_pane, - ); - Tui::draw_stack( - f, - debug_steps, - current_step, - stack_pane, - stack_labels, - draw_memory, - ); - Tui::draw_memory(f, debug_steps, current_step, memory_pane, mem_utf, draw_memory); - } else { - panic!("unable to create vertical panes") - } - } else { - panic!("unable to create footer / app") - } - } - - fn square_layout( - f: &mut Frame, - address: Address, - debug_steps: &[DebugStep], - opcode_list: &[String], - current_step: usize, - draw_memory: &mut DrawMemory, - stack_labels: bool, - mem_utf: bool, - ) { - let total_size = f.size(); - - if let [app, footer] = Layout::default() - .direction(Direction::Vertical) - .constraints([Constraint::Ratio(98, 100), Constraint::Ratio(2, 100)].as_ref()) - .split(total_size)[..] - { - if let [left_pane, right_pane] = Layout::default() - .direction(Direction::Horizontal) - .constraints([Constraint::Ratio(1, 2), Constraint::Ratio(1, 2)].as_ref()) - .split(app)[..] - { - if let [stack_pane, memory_pane] = Layout::default() - .direction(Direction::Vertical) - .constraints([Constraint::Ratio(2, 5), Constraint::Ratio(3, 5)].as_ref()) - .split(right_pane)[..] - { - Tui::draw_footer(f, footer); - Tui::draw_op_list( - f, - address, - debug_steps, - opcode_list, - current_step, - draw_memory, - left_pane, - ); - Tui::draw_stack( - f, - debug_steps, - current_step, - stack_pane, - stack_labels, - draw_memory, - ); - Tui::draw_memory( - f, - debug_steps, - current_step, - memory_pane, - mem_utf, - draw_memory, - ); - } else { - panic!("Couldn't generate horizontal split layout 1:2."); - } - } else { - panic!("Couldn't generate vertical split layout 1:2."); - } - } else { - panic!("Couldn't generate application & footer") - } - } - - fn draw_footer(f: &mut Frame, area: Rect) { - let block_controls = Block::default(); - - let text_output = Text::from(Span::styled( - "[q]: quit | [k/j]: prev/next op | [a/s]: prev/next jump | [c/C]: prev/next call | [g/G]: start/end | [t]: toggle stack labels | [m]: toggle memory decoding | [shift + j/k]: scroll stack | [ctrl + j/k]: scroll memory", - Style::default().add_modifier(Modifier::DIM) - )); - let paragraph = Paragraph::new(text_output) - .block(block_controls) - .alignment(Alignment::Center) - .wrap(Wrap { trim: false }); - f.render_widget(paragraph, area); - } - - fn draw_op_list( - f: &mut Frame, - address: Address, - debug_steps: &[DebugStep], - opcode_list: &[String], - current_step: usize, - draw_memory: &mut DrawMemory, - area: Rect, - ) { - let block_source_code = Block::default() - .title(format!( - "Address: {:?} | PC: {} | Gas used in call: {}", - address, - if let Some(step) = debug_steps.get(current_step) { - step.pc.to_string() - } else { - "END".to_string() - }, - debug_steps[current_step].total_gas_used, - )) - .borders(Borders::ALL); - let mut text_output: Vec = Vec::new(); - - let display_start; - - let height = area.height as i32; - let extra_top_lines = height / 2; - let prev_start = draw_memory.current_startline; - let abs_min_start = 0; - let abs_max_start = (opcode_list.len() as i32 - 1) - (height / 2); - let mut min_start = - max(current_step as i32 - height + extra_top_lines, abs_min_start) as usize; - - let mut max_start = - max(min(current_step as i32 - extra_top_lines, abs_max_start), abs_min_start) as usize; - - if min_start > max_start { - std::mem::swap(&mut min_start, &mut max_start); - } - - if prev_start < min_start { - display_start = min_start; - } else if prev_start > max_start { - display_start = max_start; - } else { - display_start = prev_start; - } - draw_memory.current_startline = display_start; - - let max_pc_len = - debug_steps.iter().fold(0, |max_val, val| val.pc.max(max_val)).to_string().len(); - - let mut add_new_line = |line_number| { - let bg_color = if line_number == current_step { Color::DarkGray } else { Color::Reset }; - - let line_number_format = if line_number == current_step { - let step: &DebugStep = &debug_steps[line_number]; - format!("{:0>max_pc_len$x}|▶", step.pc) - } else if line_number < debug_steps.len() { - let step: &DebugStep = &debug_steps[line_number]; - format!("{:0>max_pc_len$x}| ", step.pc) - } else { - "END CALL".to_string() - }; - - if let Some(op) = opcode_list.get(line_number) { - text_output.push(Spans::from(Span::styled( - format!("{line_number_format}{op}"), - Style::default().fg(Color::White).bg(bg_color), - ))); - } else { - text_output.push(Spans::from(Span::styled( - line_number_format, - Style::default().fg(Color::White).bg(bg_color), - ))); - } - }; - for number in display_start..opcode_list.len() { - add_new_line(number); - } - add_new_line(opcode_list.len()); - let paragraph = - Paragraph::new(text_output).block(block_source_code).wrap(Wrap { trim: true }); - f.render_widget(paragraph, area); - } - - fn draw_stack( - f: &mut Frame, - debug_steps: &[DebugStep], - current_step: usize, - area: Rect, - stack_labels: bool, - draw_memory: &DrawMemory, - ) { - let stack = &debug_steps[current_step].stack; - let stack_space = - Block::default().title(format!("Stack: {}", stack.len())).borders(Borders::ALL); - let min_len = usize::max(format!("{}", stack.len()).len(), 2); - - let indices_affected = stack_indices_affected(debug_steps[current_step].instruction.0); - - let text: Vec = stack - .iter() - .rev() - .enumerate() - .skip(draw_memory.current_stack_startline) - .map(|(i, stack_item)| { - let affected = - indices_affected.iter().find(|(affected_index, _name)| *affected_index == i); - - let mut words: Vec = (0..32) - .rev() - .map(|i| stack_item.byte(i)) - .map(|byte| { - Span::styled( - format!("{byte:02x} "), - if affected.is_some() { - Style::default().fg(Color::Cyan) - } else if byte == 0 { - Style::default().add_modifier(Modifier::DIM) - } else { - Style::default().fg(Color::White) - }, - ) - }) - .collect(); - - if stack_labels { - if let Some((_, name)) = affected { - words.push(Span::raw(format!("| {name}"))); - } else { - words.push(Span::raw("| ".to_string())); - } - } - - let mut spans = vec![Span::styled( - format!("{i:0min_len$}| "), - Style::default().fg(Color::White), - )]; - spans.extend(words); - spans.push(Span::raw("\n")); - - Spans::from(spans) - }) - .collect(); - - let paragraph = Paragraph::new(text).block(stack_space).wrap(Wrap { trim: true }); - f.render_widget(paragraph, area); - } - - fn draw_memory( - f: &mut Frame, - debug_steps: &[DebugStep], - current_step: usize, - area: Rect, - mem_utf8: bool, - draw_mem: &DrawMemory, - ) { - let memory = &debug_steps[current_step].memory; - let stack_space = Block::default() - .title(format!("Memory (max expansion: {} bytes)", memory.effective_len())) - .borders(Borders::ALL); - let memory = memory.data(); - let max_i = memory.len() / 32; - let min_len = format!("{:x}", max_i * 32).len(); - - let mut word = None; - let mut color = None; - let stack_len = debug_steps[current_step].stack.len(); - if stack_len > 0 { - let w = debug_steps[current_step].stack[stack_len - 1]; - match debug_steps[current_step].instruction.0 { - opcode::MLOAD => { - word = Some(w.as_usize() / 32); - color = Some(Color::Cyan); - } - opcode::MSTORE => { - word = Some(w.as_usize() / 32); - color = Some(Color::Red); - } - _ => {} - } - } - - if current_step > 0 { - let prev_step = current_step - 1; - let stack_len = debug_steps[prev_step].stack.len(); - if debug_steps[prev_step].instruction.0 == opcode::MSTORE { - let prev_top = debug_steps[prev_step].stack[stack_len - 1]; - word = Some(prev_top.as_usize() / 32); - color = Some(Color::Green); - } - } - - let text: Vec = memory - .chunks(32) - .enumerate() - .skip(draw_mem.current_mem_startline) - .map(|(i, mem_word)| { - let words: Vec = mem_word - .iter() - .map(|byte| { - Span::styled( - format!("{byte:02x} "), - if let (Some(w), Some(color)) = (word, color) { - if i == w { - Style::default().fg(color) - } else if *byte == 0 { - Style::default().add_modifier(Modifier::DIM) - } else { - Style::default().fg(Color::White) - } - } else if *byte == 0 { - Style::default().add_modifier(Modifier::DIM) - } else { - Style::default().fg(Color::White) - }, - ) - }) - .collect(); - - let mut spans = vec![Span::styled( - format!("{:0min_len$x}| ", i * 32), - Style::default().fg(Color::White), - )]; - spans.extend(words); - - if mem_utf8 { - let chars: Vec = mem_word - .chunks(4) - .map(|utf| { - if let Ok(utf_str) = std::str::from_utf8(utf) { - Span::raw(utf_str.replace(char::from(0), ".")) - } else { - Span::raw(".") - } - }) - .collect(); - spans.push(Span::raw("|")); - spans.extend(chars); - } - - spans.push(Span::raw("\n")); - - Spans::from(spans) - }) - .collect(); - let paragraph = Paragraph::new(text).block(stack_space).wrap(Wrap { trim: true }); - f.render_widget(paragraph, area); - } -} - -enum Interrupt { - KeyPressed(KeyEvent), - MouseEvent(MouseEvent), - IntervalElapsed, -} - -struct DrawMemory { - pub current_startline: usize, - pub inner_call_index: usize, - pub current_mem_startline: usize, - pub current_stack_startline: usize, -} - -impl DrawMemory { - fn default() -> Self { - DrawMemory { - current_startline: 0, - inner_call_index: 0, - current_mem_startline: 0, - current_stack_startline: 0, - } - } -} - -fn stack_indices_affected(op: u8) -> Vec<(usize, &'static str)> { - match op { - 0x01 => vec![(0, "a"), (1, "b")], - 0x02 => vec![(0, "a"), (1, "b")], - 0x03 => vec![(0, "a"), (1, "b")], - 0x04 => vec![(0, "a"), (1, "b")], - 0x05 => vec![(0, "a"), (1, "b")], - 0x06 => vec![(0, "a"), (1, "b")], - 0x07 => vec![(0, "a"), (1, "b")], - 0x08 => vec![(0, "a"), (1, "b"), (2, "mod")], - 0x09 => vec![(0, "a"), (1, "b"), (2, "mod")], - 0x0a => vec![(0, "base"), (1, "exp")], - 0x0b => vec![(0, "i"), (1, "a")], - 0x10 => vec![(0, "a"), (1, "b")], - 0x11 => vec![(0, "a"), (1, "b")], - 0x12 => vec![(0, "a"), (1, "b")], - 0x13 => vec![(0, "a"), (1, "b")], - 0x14 => vec![(0, "a"), (1, "b")], - 0x15 => vec![(0, "a")], - 0x16 => vec![(0, "a"), (1, "b")], - 0x17 => vec![(0, "a"), (1, "b")], - 0x18 => vec![(0, "a"), (1, "b")], - 0x19 => vec![(0, "a")], - 0x1a => vec![(0, "i"), (1, "a")], - 0x1b => vec![(0, "shift"), (1, "a")], - 0x1c => vec![(0, "shift"), (1, "a")], - 0x1d => vec![(0, "shift"), (1, "a")], - 0x20 => vec![(0, "offset"), (1, "length")], - 0x31 => vec![(0, "address")], - 0x35 => vec![(0, "offset")], - 0x37 => vec![(0, "dst"), (1, "src"), (2, "length")], - 0x39 => vec![(0, "dst"), (1, "src"), (2, "length")], - 0x3b => vec![(0, "address")], - 0x3c => vec![(0, "address"), (1, "dst"), (2, "src"), (3, "length")], - 0x3e => vec![(0, "dst"), (1, "src"), (2, "length")], - 0x3f => vec![(0, "address")], - 0x40 => vec![(0, "number")], - 0x50 => vec![(0, "a")], - 0x51 => vec![(0, "offset")], - 0x52 => vec![(0, "offset"), (1, "a")], - 0x53 => vec![(0, "offset"), (1, "a")], - 0x54 => vec![(0, "key")], - 0x55 => vec![(0, "key"), (1, "a")], - 0x56 => vec![(0, "dst")], - 0x57 => vec![(0, "dst"), (1, "cond")], - 0x80 => vec![(0, "a")], - 0x81 => vec![(1, "a")], - 0x82 => vec![(2, "a")], - 0x83 => vec![(3, "a")], - 0x84 => vec![(4, "a")], - 0x85 => vec![(5, "a")], - 0x86 => vec![(6, "a")], - 0x87 => vec![(7, "a")], - 0x88 => vec![(8, "a")], - 0x89 => vec![(9, "a")], - 0x8a => vec![(10, "a")], - 0x8b => vec![(11, "a")], - 0x8c => vec![(12, "a")], - 0x8d => vec![(13, "a")], - 0x8e => vec![(14, "a")], - 0x8f => vec![(15, "a")], - 0x90 => vec![(0, "a"), (1, "a")], - 0x91 => vec![(0, "a"), (2, "a")], - 0x92 => vec![(0, "a"), (3, "a")], - 0x93 => vec![(0, "a"), (4, "a")], - 0x94 => vec![(0, "a"), (5, "a")], - 0x95 => vec![(0, "a"), (6, "a")], - 0x96 => vec![(0, "a"), (7, "a")], - 0x97 => vec![(0, "a"), (8, "a")], - 0x98 => vec![(0, "a"), (9, "a")], - 0x99 => vec![(0, "a"), (10, "a")], - 0x9a => vec![(0, "a"), (11, "a")], - 0x9b => vec![(0, "a"), (12, "a")], - 0x9c => vec![(0, "a"), (13, "a")], - 0x9d => vec![(0, "a"), (14, "a")], - 0x9e => vec![(0, "a"), (15, "a")], - 0x9f => vec![(0, "a"), (16, "a")], - 0xa0 => vec![(0, "offset"), (1, "length")], - 0xa1 => vec![(0, "offset"), (1, "length"), (2, "topic")], - 0xa2 => vec![(0, "offset"), (1, "length"), (2, "topic1"), (3, "topic2")], - 0xa3 => vec![(0, "offset"), (1, "length"), (2, "topic1"), (3, "topic2"), (4, "topic3")], - 0xa4 => vec![ - (0, "offset"), - (1, "length"), - (2, "topic1"), - (3, "topic2"), - (4, "topic3"), - (5, "topic4"), - ], - 0xf0 => vec![(0, "value"), (1, "offset"), (2, "length")], - 0xf1 => vec![ - (0, "gas"), - (1, "address"), - (2, "value"), - (3, "cd_offset"), - (4, "cd_length"), - (5, "rd_offset"), - (6, "rd_length"), - ], - 0xf2 => vec![ - (0, "gas"), - (1, "address"), - (2, "value"), - (3, "cd_offset"), - (4, "cd_length"), - (5, "rd_offset"), - (6, "rd_length"), - ], - 0xf3 => vec![(0, "offset"), (1, "length")], - 0xf4 => vec![ - (0, "gas"), - (1, "address"), - (2, "cd_offset"), - (3, "cd_length"), - (4, "rd_offset"), - (5, "rd_length"), - ], - 0xf5 => vec![(0, "value"), (1, "offset"), (2, "length"), (3, "salt")], - 0xfa => vec![ - (0, "gas"), - (1, "address"), - (2, "cd_offset"), - (3, "cd_length"), - (4, "rd_offset"), - (5, "rd_length"), - ], - 0xfd => vec![(0, "offset"), (1, "length")], - 0xff => vec![(0, "address")], - _ => vec![], - } -} diff --git a/snark-verifier/src/loader/evm/util.rs b/snark-verifier/src/loader/evm/util.rs index 5df077f6..747849d4 100644 --- a/snark-verifier/src/loader/evm/util.rs +++ b/snark-verifier/src/loader/evm/util.rs @@ -8,12 +8,11 @@ use std::{ process::{Command, Stdio}, }; -pub use primitive_types::{H160 as Address, H256, U256, U512}; +pub use executor::deploy_and_call; +pub use revm::primitives::ruint::aliases::{B160 as Address, B256, U256, U512}; pub(crate) mod executor; -pub use executor::ExecutorBuilder; - /// Memory chunk in EVM. #[derive(Debug)] pub struct MemoryChunk { @@ -55,7 +54,7 @@ pub fn fe_to_u256(f: F) -> U256 where F: PrimeField, { - U256::from_little_endian(f.to_repr().as_ref()) + U256::from_le_bytes(f.to_repr()) } /// Convert a [`U256`] into a [`PrimeField`]. @@ -64,9 +63,7 @@ where F: PrimeField, { let value = value % modulus::(); - let mut repr = F::Repr::default(); - value.to_little_endian(repr.as_mut()); - F::from_repr(repr).unwrap() + F::from_repr(value.to_le_bytes::<32>()).unwrap() } /// Returns modulus of [`PrimeField`] as [`U256`]. @@ -74,7 +71,7 @@ pub fn modulus() -> U256 where F: PrimeField, { - U256::from_little_endian((-F::ONE).to_repr().as_ref()) + 1 + U256::from_le_bytes((-F::ONE).to_repr()) + U256::from(1) } /// Encode instances and proof into calldata. diff --git a/snark-verifier/src/loader/evm/util/executor.rs b/snark-verifier/src/loader/evm/util/executor.rs index 17062028..e2c5bb2c 100644 --- a/snark-verifier/src/loader/evm/util/executor.rs +++ b/snark-verifier/src/loader/evm/util/executor.rs @@ -1,815 +1,59 @@ -//! Copied and modified from -//! - -use crate::loader::evm::{Address, H256, U256}; -use bytes::Bytes; use revm::{ - evm_inner, opcode, spec_opcode_gas, Account, BlockEnv, CallInputs, CallScheme, CreateInputs, - CreateScheme, Database, DatabaseCommit, EVMData, Env, ExecutionResult, Gas, GasInspector, - InMemoryDB, Inspector, Interpreter, Memory, OpCode, Return, TransactOut, TransactTo, TxEnv, + primitives::{CreateScheme, ExecutionResult, Output, TransactTo, TxEnv}, + InMemoryDB, EVM, }; -use sha3::{Digest, Keccak256}; -use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc}; -macro_rules! return_ok { - () => { - Return::Continue | Return::Stop | Return::Return | Return::SelfDestruct +/// Deploy contract and then call with calldata. +/// Returns gas_used of call to deployed contract if both transactions are successful. +pub fn deploy_and_call(deployment_code: Vec, calldata: Vec) -> Result { + let mut evm = EVM { + env: Default::default(), + db: Some(InMemoryDB::default()), }; -} - -fn keccak256(data: impl AsRef<[u8]>) -> [u8; 32] { - Keccak256::digest(data.as_ref()).into() -} - -fn get_contract_address(sender: impl Into
, nonce: impl Into) -> Address { - let mut stream = rlp::RlpStream::new(); - stream.begin_list(2); - stream.append(&sender.into()); - stream.append(&nonce.into()); - - let hash = keccak256(&stream.out()); - - let mut bytes = [0u8; 20]; - bytes.copy_from_slice(&hash[12..]); - Address::from(bytes) -} - -fn get_create2_address( - from: impl Into
, - salt: [u8; 32], - init_code: impl Into, -) -> Address { - get_create2_address_from_hash(from, salt, keccak256(init_code.into().as_ref()).to_vec()) -} - -fn get_create2_address_from_hash( - from: impl Into
, - salt: [u8; 32], - init_code_hash: impl Into, -) -> Address { - let bytes = - [&[0xff], from.into().as_bytes(), salt.as_slice(), init_code_hash.into().as_ref()].concat(); - - let hash = keccak256(bytes); - - let mut bytes = [0u8; 20]; - bytes.copy_from_slice(&hash[12..]); - Address::from(bytes) -} - -fn get_create_address(call: &CreateInputs, nonce: u64) -> Address { - match call.scheme { - CreateScheme::Create => get_contract_address(call.caller, nonce), - CreateScheme::Create2 { salt } => { - let mut buffer: [u8; 4 * 8] = [0; 4 * 8]; - salt.to_big_endian(&mut buffer); - get_create2_address(call.caller, buffer, call.init_code.clone()) - } - } -} - -#[derive(Clone, Debug, Default)] -pub struct Log { - pub address: Address, - pub topics: Vec, - pub data: Bytes, -} - -#[derive(Clone, Debug, Default)] -struct LogCollector { - logs: Vec, -} - -impl Inspector for LogCollector { - fn log(&mut self, _: &mut EVMData<'_, DB>, address: &Address, topics: &[H256], data: &Bytes) { - self.logs.push(Log { address: *address, topics: topics.to_vec(), data: data.clone() }); - } - - fn call( - &mut self, - _: &mut EVMData<'_, DB>, - call: &mut CallInputs, - _: bool, - ) -> (Return, Gas, Bytes) { - (Return::Continue, Gas::new(call.gas_limit), Bytes::new()) - } -} - -#[derive(Clone, Debug, Copy)] -pub enum CallKind { - Call, - StaticCall, - CallCode, - DelegateCall, - Create, - Create2, -} - -#[allow(clippy::derivable_impls)] -impl Default for CallKind { - fn default() -> Self { - CallKind::Call - } -} - -impl From for CallKind { - fn from(scheme: CallScheme) -> Self { - match scheme { - CallScheme::Call => CallKind::Call, - CallScheme::StaticCall => CallKind::StaticCall, - CallScheme::CallCode => CallKind::CallCode, - CallScheme::DelegateCall => CallKind::DelegateCall, - } - } -} - -impl From for CallKind { - fn from(create: CreateScheme) -> Self { - match create { - CreateScheme::Create => CallKind::Create, - CreateScheme::Create2 { .. } => CallKind::Create2, - } - } -} - -#[derive(Clone, Debug, Default)] -pub struct DebugArena { - pub arena: Vec, -} - -impl DebugArena { - fn push_node(&mut self, mut new_node: DebugNode) -> usize { - fn recursively_push( - arena: &mut Vec, - entry: usize, - mut new_node: DebugNode, - ) -> usize { - match new_node.depth { - _ if arena[entry].depth == new_node.depth - 1 => { - let id = arena.len(); - new_node.location = arena[entry].children.len(); - new_node.parent = Some(entry); - arena[entry].children.push(id); - arena.push(new_node); - id - } - _ => { - let child = *arena[entry].children.last().unwrap(); - recursively_push(arena, child, new_node) - } - } - } - - if self.arena.is_empty() { - self.arena.push(new_node); - 0 - } else if new_node.depth == 0 { - let id = self.arena.len(); - new_node.location = self.arena[0].children.len(); - new_node.parent = Some(0); - self.arena[0].children.push(id); - self.arena.push(new_node); - id - } else { - recursively_push(&mut self.arena, 0, new_node) - } - } - - #[cfg(test)] - pub fn flatten(&self, entry: usize) -> Vec<(Address, Vec, CallKind)> { - let node = &self.arena[entry]; - - let mut flattened = vec![]; - if !node.steps.is_empty() { - flattened.push((node.address, node.steps.clone(), node.kind)); - } - flattened.extend(node.children.iter().flat_map(|child| self.flatten(*child))); - - flattened - } -} - -#[derive(Clone, Debug, Default)] -pub struct DebugNode { - pub parent: Option, - pub children: Vec, - pub location: usize, - pub address: Address, - pub kind: CallKind, - pub depth: usize, - pub steps: Vec, -} - -#[derive(Clone, Debug)] -pub struct DebugStep { - pub stack: Vec, - pub memory: Memory, - pub instruction: Instruction, - pub push_bytes: Option>, - pub pc: usize, - pub total_gas_used: u64, -} - -impl Default for DebugStep { - fn default() -> Self { - Self { - stack: vec![], - memory: Memory::new(), - instruction: Instruction(revm::opcode::INVALID), - push_bytes: None, - pc: 0, - total_gas_used: 0, - } - } -} - -impl DebugStep { - #[cfg(test)] - pub fn pretty_opcode(&self) -> String { - if let Some(push_bytes) = &self.push_bytes { - format!("{}(0x{})", self.instruction, hex::encode(push_bytes)) - } else { - self.instruction.to_string() - } - } -} - -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct Instruction(pub u8); - -impl From for Instruction { - fn from(op: u8) -> Instruction { - Instruction(op) - } -} - -impl Display for Instruction { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{}", - OpCode::try_from_u8(self.0).map_or_else( - || format!("UNDEFINED(0x{:02x})", self.0), - |opcode| opcode.as_str().to_string(), - ) - ) - } -} - -#[derive(Clone, Debug)] -struct Debugger { - arena: DebugArena, - head: usize, - context: Address, - gas_inspector: Rc>, -} - -impl Debugger { - fn new(gas_inspector: Rc>) -> Self { - Self { - arena: Default::default(), - head: Default::default(), - context: Default::default(), - gas_inspector, - } - } - - fn enter(&mut self, depth: usize, address: Address, kind: CallKind) { - self.context = address; - self.head = self.arena.push_node(DebugNode { depth, address, kind, ..Default::default() }); - } - - fn exit(&mut self) { - if let Some(parent_id) = self.arena.arena[self.head].parent { - let DebugNode { depth, address, kind, .. } = self.arena.arena[parent_id]; - self.context = address; - self.head = - self.arena.push_node(DebugNode { depth, address, kind, ..Default::default() }); - } - } -} - -impl Inspector for Debugger { - fn step( - &mut self, - interpreter: &mut Interpreter, - data: &mut EVMData<'_, DB>, - _is_static: bool, - ) -> Return { - let pc = interpreter.program_counter(); - let op = interpreter.contract.bytecode.bytecode()[pc]; - - let opcode_infos = spec_opcode_gas(data.env.cfg.spec_id); - let opcode_info = &opcode_infos[op as usize]; - - let push_size = if opcode_info.is_push() { (op - opcode::PUSH1 + 1) as usize } else { 0 }; - let push_bytes = match push_size { - 0 => None, - n => { - let start = pc + 1; - let end = start + n; - Some(interpreter.contract.bytecode.bytecode()[start..end].to_vec()) - } - }; - - let spent = interpreter.gas.limit() - self.gas_inspector.borrow().gas_remaining(); - let total_gas_used = spent - (interpreter.gas.refunded() as u64).min(spent / 5); - - self.arena.arena[self.head].steps.push(DebugStep { - pc, - stack: interpreter.stack().data().clone(), - memory: interpreter.memory.clone(), - instruction: Instruction(op), - push_bytes, - total_gas_used, - }); - - Return::Continue - } - - fn call( - &mut self, - data: &mut EVMData<'_, DB>, - call: &mut CallInputs, - _: bool, - ) -> (Return, Gas, Bytes) { - self.enter( - data.journaled_state.depth() as usize, - call.context.code_address, - call.context.scheme.into(), - ); - - (Return::Continue, Gas::new(call.gas_limit), Bytes::new()) - } - fn call_end( - &mut self, - _: &mut EVMData<'_, DB>, - _: &CallInputs, - gas: Gas, - status: Return, - retdata: Bytes, - _: bool, - ) -> (Return, Gas, Bytes) { - self.exit(); - - (status, gas, retdata) - } - - fn create( - &mut self, - data: &mut EVMData<'_, DB>, - call: &mut CreateInputs, - ) -> (Return, Option
, Gas, Bytes) { - let nonce = data.journaled_state.account(call.caller).info.nonce; - self.enter( - data.journaled_state.depth() as usize, - get_create_address(call, nonce), - CallKind::Create, - ); - - (Return::Continue, None, Gas::new(call.gas_limit), Bytes::new()) - } - - fn create_end( - &mut self, - _: &mut EVMData<'_, DB>, - _: &CreateInputs, - status: Return, - address: Option
, - gas: Gas, - retdata: Bytes, - ) -> (Return, Option
, Gas, Bytes) { - self.exit(); - - (status, address, gas, retdata) - } -} - -macro_rules! call_inspectors { - ($id:ident, [ $($inspector:expr),+ ], $call:block) => { - $({ - if let Some($id) = $inspector { - $call; - } - })+ - } -} - -struct InspectorData { - logs: Vec, - debug: Option, -} - -#[derive(Default)] -struct InspectorStack { - gas: Option>>, - logs: Option, - debugger: Option, -} - -impl InspectorStack { - fn collect_inspector_states(self) -> InspectorData { - InspectorData { - logs: self.logs.map(|logs| logs.logs).unwrap_or_default(), - debug: self.debugger.map(|debugger| debugger.arena), - } - } -} - -impl Inspector for InspectorStack { - fn initialize_interp( - &mut self, - interpreter: &mut Interpreter, - data: &mut EVMData<'_, DB>, - is_static: bool, - ) -> Return { - call_inspectors!( - inspector, - [ - &mut self.gas.as_deref().map(|gas| gas.borrow_mut()), - &mut self.logs, - &mut self.debugger - ], - { - let status = inspector.initialize_interp(interpreter, data, is_static); - - if status != Return::Continue { - return status; - } - } - ); - - Return::Continue - } - - fn step( - &mut self, - interpreter: &mut Interpreter, - data: &mut EVMData<'_, DB>, - is_static: bool, - ) -> Return { - call_inspectors!( - inspector, - [ - &mut self.gas.as_deref().map(|gas| gas.borrow_mut()), - &mut self.logs, - &mut self.debugger - ], - { - let status = inspector.step(interpreter, data, is_static); - - if status != Return::Continue { - return status; - } - } - ); - - Return::Continue - } - - fn log( - &mut self, - evm_data: &mut EVMData<'_, DB>, - address: &Address, - topics: &[H256], - data: &Bytes, - ) { - call_inspectors!(inspector, [&mut self.logs], { - inspector.log(evm_data, address, topics, data); - }); - } - - fn step_end( - &mut self, - interpreter: &mut Interpreter, - data: &mut EVMData<'_, DB>, - is_static: bool, - status: Return, - ) -> Return { - call_inspectors!( - inspector, - [ - &mut self.gas.as_deref().map(|gas| gas.borrow_mut()), - &mut self.logs, - &mut self.debugger - ], - { - let status = inspector.step_end(interpreter, data, is_static, status); - - if status != Return::Continue { - return status; - } - } - ); - - Return::Continue - } - - fn call( - &mut self, - data: &mut EVMData<'_, DB>, - call: &mut CallInputs, - is_static: bool, - ) -> (Return, Gas, Bytes) { - call_inspectors!( - inspector, - [ - &mut self.gas.as_deref().map(|gas| gas.borrow_mut()), - &mut self.logs, - &mut self.debugger - ], - { - let (status, gas, retdata) = inspector.call(data, call, is_static); - - if status != Return::Continue { - return (status, gas, retdata); - } - } - ); - - (Return::Continue, Gas::new(call.gas_limit), Bytes::new()) - } - - fn call_end( - &mut self, - data: &mut EVMData<'_, DB>, - call: &CallInputs, - remaining_gas: Gas, - status: Return, - retdata: Bytes, - is_static: bool, - ) -> (Return, Gas, Bytes) { - call_inspectors!( - inspector, - [ - &mut self.gas.as_deref().map(|gas| gas.borrow_mut()), - &mut self.logs, - &mut self.debugger - ], - { - let (new_status, new_gas, new_retdata) = inspector.call_end( - data, - call, - remaining_gas, - status, - retdata.clone(), - is_static, - ); - - if new_status != status || (new_status == Return::Revert && new_retdata != retdata) - { - return (new_status, new_gas, new_retdata); - } - } - ); - - (status, remaining_gas, retdata) - } - - fn create( - &mut self, - data: &mut EVMData<'_, DB>, - call: &mut CreateInputs, - ) -> (Return, Option
, Gas, Bytes) { - call_inspectors!( - inspector, - [ - &mut self.gas.as_deref().map(|gas| gas.borrow_mut()), - &mut self.logs, - &mut self.debugger - ], - { - let (status, addr, gas, retdata) = inspector.create(data, call); - - if status != Return::Continue { - return (status, addr, gas, retdata); - } - } - ); - - (Return::Continue, None, Gas::new(call.gas_limit), Bytes::new()) - } - - fn create_end( - &mut self, - data: &mut EVMData<'_, DB>, - call: &CreateInputs, - status: Return, - address: Option
, - remaining_gas: Gas, - retdata: Bytes, - ) -> (Return, Option
, Gas, Bytes) { - call_inspectors!( - inspector, - [ - &mut self.gas.as_deref().map(|gas| gas.borrow_mut()), - &mut self.logs, - &mut self.debugger - ], - { - let (new_status, new_address, new_gas, new_retdata) = inspector.create_end( - data, - call, - status, - address, - remaining_gas, - retdata.clone(), - ); - - if new_status != status { - return (new_status, new_address, new_gas, new_retdata); - } - } - ); - - (status, address, remaining_gas, retdata) - } - - fn selfdestruct(&mut self) { - call_inspectors!(inspector, [&mut self.logs, &mut self.debugger], { - Inspector::::selfdestruct(inspector); - }); - } -} - -/// Call result. -#[derive(Debug)] -pub struct RawCallResult { - /// Exit reason - pub exit_reason: Return, - /// If the call is reverted or not. - pub reverted: bool, - /// Returndata - pub result: Bytes, - /// Gas used - pub gas_used: u64, - /// Gas refunded - pub gas_refunded: u64, - /// Logs emitted during the call - pub logs: Vec, - /// Debug information if any - pub debug: Option, - /// State changes if any - pub state_changeset: Option>, - /// Environment - pub env: Env, - /// Output - pub out: TransactOut, -} - -#[derive(Clone, Debug)] -pub struct DeployResult { - pub exit_reason: Return, - pub reverted: bool, - pub address: Option
, - pub gas_used: u64, - pub gas_refunded: u64, - pub logs: Vec, - pub debug: Option, - pub env: Env, -} - -/// Executor builder. -#[derive(Debug, Default)] -pub struct ExecutorBuilder { - debugger: bool, - gas_limit: Option, -} - -impl ExecutorBuilder { - /// Set `debugger`. - pub fn set_debugger(mut self, enable: bool) -> Self { - self.debugger = enable; - self - } - - /// Set `gas_limit`. - pub fn with_gas_limit(mut self, gas_limit: U256) -> Self { - self.gas_limit = Some(gas_limit); - self - } - - /// Initialize an `Executor`. - pub fn build(self) -> Executor { - Executor::new(self.debugger, self.gas_limit.unwrap_or(U256::MAX)) - } -} - -#[derive(Clone, Debug)] -pub struct Executor { - db: InMemoryDB, - debugger: bool, - gas_limit: U256, -} - -impl Executor { - fn new(debugger: bool, gas_limit: U256) -> Self { - Executor { db: InMemoryDB::default(), debugger, gas_limit } - } - - pub fn db_mut(&mut self) -> &mut InMemoryDB { - &mut self.db - } - - pub fn deploy(&mut self, from: Address, code: Bytes, value: U256) -> DeployResult { - let env = self.build_test_env(from, TransactTo::Create(CreateScheme::Create), code, value); - let result = self.call_raw_with_env(env); - self.commit(&result); - - let RawCallResult { exit_reason, out, gas_used, gas_refunded, logs, debug, env, .. } = - result; - - let address = match (exit_reason, out) { - (return_ok!(), TransactOut::Create(_, Some(address))) => Some(address), - _ => None, - }; - - DeployResult { - exit_reason, - reverted: !matches!(exit_reason, return_ok!()), - address, - gas_used, - gas_refunded, - logs, - debug, - env, - } - } - - pub fn call_raw( - &self, - from: Address, - to: Address, - calldata: Bytes, - value: U256, - ) -> RawCallResult { - let env = self.build_test_env(from, TransactTo::Call(to), calldata, value); - self.call_raw_with_env(env) - } - - fn call_raw_with_env(&self, mut env: Env) -> RawCallResult { - let mut inspector = self.inspector(); - let result = - evm_inner::<_, true>(&mut env, &mut self.db.clone(), &mut inspector).transact(); - let (exec_result, state_changeset) = result; - let ExecutionResult { exit_reason, gas_refunded, gas_used, out, .. } = exec_result; - - let result = match out { - TransactOut::Call(ref data) => data.to_owned(), - _ => Bytes::default(), - }; - let InspectorData { logs, debug } = inspector.collect_inspector_states(); - - RawCallResult { - exit_reason, - reverted: !matches!(exit_reason, return_ok!()), - result, - gas_used, - gas_refunded, - logs: logs.to_vec(), - debug, - state_changeset: Some(state_changeset.into_iter().collect()), - env, - out, - } - } + evm.env.tx = TxEnv { + gas_limit: u64::MAX, + transact_to: TransactTo::Create(CreateScheme::Create), + data: deployment_code.into(), + ..Default::default() + }; - fn commit(&mut self, result: &RawCallResult) { - if let Some(state_changeset) = result.state_changeset.as_ref() { - self.db.commit(state_changeset.clone().into_iter().collect()); - } - } + let result = evm.transact_commit().unwrap(); + let contract = match result { + ExecutionResult::Success { + output: Output::Create(_, Some(contract)), + .. + } => contract, + ExecutionResult::Revert { gas_used, output } => { + return Err(format!( + "Contract deployment transaction reverts with gas_used {gas_used} and output {:#x}", + output + )) + } + ExecutionResult::Halt { reason, gas_used } => return Err(format!( + "Contract deployment transaction halts unexpectedly with gas_used {gas_used} and reason {:?}", + reason + )), + _ => unreachable!(), + }; - fn inspector(&self) -> InspectorStack { - let mut stack = - InspectorStack { logs: Some(LogCollector::default()), ..Default::default() }; - if self.debugger { - let gas_inspector = Rc::new(RefCell::new(GasInspector::default())); - stack.gas = Some(gas_inspector.clone()); - stack.debugger = Some(Debugger::new(gas_inspector)); - } - stack - } + evm.env.tx = TxEnv { + gas_limit: u64::MAX, + transact_to: TransactTo::Call(contract), + data: calldata.into(), + ..Default::default() + }; - fn build_test_env( - &self, - caller: Address, - transact_to: TransactTo, - data: Bytes, - value: U256, - ) -> Env { - Env { - block: BlockEnv { gas_limit: self.gas_limit, ..BlockEnv::default() }, - tx: TxEnv { - caller, - transact_to, - data, - value, - gas_limit: self.gas_limit.as_u64(), - ..TxEnv::default() - }, - ..Env::default() - } + let result = evm.transact_commit().unwrap(); + match result { + ExecutionResult::Success { gas_used, .. } => Ok(gas_used), + ExecutionResult::Revert { gas_used, output } => Err(format!( + "Contract call transaction reverts with gas_used {gas_used} and output {:#x}", + output + )), + ExecutionResult::Halt { reason, gas_used } => Err(format!( + "Contract call transaction halts unexpectedly with gas_used {gas_used} and reason {:?}", + reason + )), } } diff --git a/snark-verifier/src/pcs/kzg/decider.rs b/snark-verifier/src/pcs/kzg/decider.rs index 04f2caaf..d55e0a57 100644 --- a/snark-verifier/src/pcs/kzg/decider.rs +++ b/snark-verifier/src/pcs/kzg/decider.rs @@ -127,10 +127,10 @@ mod evm { let x = coordinates.x().to_repr(); let y = coordinates.y().to_repr(); ( - U256::from_little_endian(&x.as_ref()[32..]), - U256::from_little_endian(&x.as_ref()[..32]), - U256::from_little_endian(&y.as_ref()[32..]), - U256::from_little_endian(&y.as_ref()[..32]), + U256::try_from_le_slice(&x.as_ref()[32..]).unwrap(), + U256::try_from_le_slice(&x.as_ref()[..32]).unwrap(), + U256::try_from_le_slice(&y.as_ref()[32..]).unwrap(), + U256::try_from_le_slice(&y.as_ref()[..32]).unwrap(), ) }); loader.pairing(&lhs, g2, &rhs, minus_s_g2); diff --git a/snark-verifier/src/system/halo2/transcript/evm.rs b/snark-verifier/src/system/halo2/transcript/evm.rs index c71c9e79..da2c09c2 100644 --- a/snark-verifier/src/system/halo2/transcript/evm.rs +++ b/snark-verifier/src/system/halo2/transcript/evm.rs @@ -178,7 +178,7 @@ where .collect_vec(); let hash: [u8; 32] = Keccak256::digest(data).into(); self.buf = hash.to_vec(); - u256_to_fe(U256::from_big_endian(hash.as_slice())) + u256_to_fe(U256::from_be_bytes(hash)) } fn common_ec_point(&mut self, ec_point: &C) -> Result<(), Error> { @@ -274,7 +274,7 @@ where type Input = [u8; 32]; fn new(challenge_input: &[u8; 32]) -> Self { - ChallengeEvm(u256_to_fe(U256::from_big_endian(challenge_input))) + ChallengeEvm(u256_to_fe(U256::from_be_bytes(*challenge_input))) } fn get_scalar(&self) -> C::Scalar { diff --git a/snark-verifier/src/util/arithmetic.rs b/snark-verifier/src/util/arithmetic.rs index 070277a5..c34daef8 100644 --- a/snark-verifier/src/util/arithmetic.rs +++ b/snark-verifier/src/util/arithmetic.rs @@ -156,7 +156,7 @@ impl Domain { match rotation.0.cmp(&0) { Ordering::Equal => scalar, Ordering::Greater => scalar * self.gen.pow_vartime([rotation.0 as u64]), - Ordering::Less => scalar * self.gen_inv.pow_vartime([(-(rotation.0 as i64)) as u64]), + Ordering::Less => scalar * self.gen_inv.pow_vartime([(-rotation.0) as u64]), } } } diff --git a/snark-verifier/src/util/poly.rs b/snark-verifier/src/util/poly.rs index 9d688a4e..86271af4 100644 --- a/snark-verifier/src/util/poly.rs +++ b/snark-verifier/src/util/poly.rs @@ -70,12 +70,10 @@ impl Polynomial { let chunk_size = Integer::div_ceil(&self.len(), &num_threads); let mut results = vec![F::ZERO; num_threads]; parallelize_iter( - results.iter_mut().zip(self.0.chunks(chunk_size)).zip(powers(x.pow_vartime(&[ - chunk_size as u64, - 0, - 0, - 0, - ]))), + results + .iter_mut() + .zip(self.0.chunks(chunk_size)) + .zip(powers(x.pow_vartime([chunk_size as u64]))), |((result, coeffs), scalar)| *result = evaluate_serial(coeffs) * scalar, ); results.iter().fold(F::ZERO, |acc, result| acc + result) From 3aadbdf006642db370ec280d0cb9049ad0cf47ad Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Mon, 28 Aug 2023 17:14:40 -0600 Subject: [PATCH 10/19] Update: use `halo2-lib` v0.4.0 (#29) * feat: update snark-verifier * update: use `halo2-lib` v0.4.0 --- snark-verifier-sdk/Cargo.toml | 3 +- snark-verifier-sdk/benches/read_pk.rs | 7 +- snark-verifier-sdk/benches/standard_plonk.rs | 19 +- snark-verifier-sdk/examples/n_as_witness.rs | 9 +- snark-verifier-sdk/examples/range_check.rs | 62 ++--- .../examples/vkey_as_witness.rs | 9 +- snark-verifier-sdk/src/halo2/aggregation.rs | 225 +++++++----------- snark-verifier/Cargo.toml | 2 +- .../examples/evm-verifier-with-accumulator.rs | 116 +++------ snark-verifier/examples/recursion.rs | 75 +++--- snark-verifier/src/loader/halo2/shim.rs | 39 +-- snark-verifier/src/pcs/kzg/accumulator.rs | 4 +- 12 files changed, 222 insertions(+), 348 deletions(-) diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index fa423daf..a62b3b0c 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snark-verifier-sdk" -version = "0.1.3" +version = "0.1.4" edition = "2021" [dependencies] @@ -19,6 +19,7 @@ bincode = "1.3.3" ark-std = { version = "0.3.0", features = ["print-trace"], optional = true } halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } snark-verifier = { path = "../snark-verifier", default-features = false } +getset = "0.1.2" # loader_evm ethereum-types = { version = "0.14.1", default-features = false, features = ["std"], optional = true } diff --git a/snark-verifier-sdk/benches/read_pk.rs b/snark-verifier-sdk/benches/read_pk.rs index f87f52c8..4adc42fd 100644 --- a/snark-verifier-sdk/benches/read_pk.rs +++ b/snark-verifier-sdk/benches/read_pk.rs @@ -1,7 +1,7 @@ use ark_std::{end_timer, start_timer}; use criterion::Criterion; use criterion::{criterion_group, criterion_main}; -use halo2_base::gates::builder::CircuitBuilderStage; +use halo2_base::gates::circuit::CircuitBuilderStage; use halo2_base::halo2_proofs; use halo2_base::utils::fs::gen_srs; use halo2_proofs::halo2curves as halo2_curves; @@ -172,8 +172,8 @@ mod application { fn gen_application_snark(params: &ParamsKZG) -> Snark { let circuit = application::StandardPlonk::rand(OsRng); - let pk = gen_pk(params, &circuit, Some(Path::new("examples/app.pk"))); - gen_snark_shplonk(params, &pk, circuit, Some(Path::new("examples/app.snark"))) + let pk = gen_pk(params, &circuit, None); + gen_snark_shplonk(params, &pk, circuit, None::<&str>) } fn bench(c: &mut Criterion) { @@ -187,7 +187,6 @@ fn bench(c: &mut Criterion) { let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Keygen, agg_config, - None, ¶ms, snarks, VerifierUniversality::None, diff --git a/snark-verifier-sdk/benches/standard_plonk.rs b/snark-verifier-sdk/benches/standard_plonk.rs index 873f77cb..9f566999 100644 --- a/snark-verifier-sdk/benches/standard_plonk.rs +++ b/snark-verifier-sdk/benches/standard_plonk.rs @@ -1,7 +1,7 @@ use ark_std::{end_timer, start_timer}; use criterion::{criterion_group, criterion_main}; use criterion::{BenchmarkId, Criterion}; -use halo2_base::gates::builder::CircuitBuilderStage; +use halo2_base::gates::circuit::CircuitBuilderStage; use halo2_base::halo2_proofs; use halo2_base::utils::fs::gen_srs; use halo2_proofs::halo2curves as halo2_curves; @@ -19,7 +19,6 @@ use snark_verifier_sdk::{ Snark, }; use snark_verifier_sdk::{CircuitExt, SHPLONK}; -use std::path::Path; mod application { use super::halo2_curves::bn256::Fr; @@ -175,8 +174,8 @@ mod application { fn gen_application_snark(params: &ParamsKZG) -> Snark { let circuit = application::StandardPlonk::rand(OsRng); - let pk = gen_pk(params, &circuit, Some(Path::new("app.pk"))); - gen_snark_shplonk(params, &pk, circuit, Some(Path::new("app.snark"))) + let pk = gen_pk(params, &circuit, None); + gen_snark_shplonk(params, &pk, circuit, None::<&str>) } fn bench(c: &mut Criterion) { @@ -190,16 +189,16 @@ fn bench(c: &mut Criterion) { let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Keygen, agg_config, - None, ¶ms, snarks.clone(), VerifierUniversality::None, ); let start0 = start_timer!(|| "gen vk & pk"); - let pk = gen_pk(¶ms, &agg_circuit, Some(Path::new("agg.pk"))); + let pk = gen_pk(¶ms, &agg_circuit, None); end_timer!(start0); let break_points = agg_circuit.break_points(); + drop(agg_circuit); let mut group = c.benchmark_group("plonk-prover"); group.sample_size(10); @@ -211,11 +210,11 @@ fn bench(c: &mut Criterion) { let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Prover, agg_config, - Some(break_points.clone()), params, snarks.clone(), VerifierUniversality::None, - ); + ) + .use_break_points(break_points.clone()); let instances = agg_circuit.instances(); gen_proof_shplonk(params, pk, agg_circuit, instances, None) }) @@ -229,11 +228,11 @@ fn bench(c: &mut Criterion) { let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Prover, agg_config, - Some(break_points), ¶ms, snarks.clone(), VerifierUniversality::None, - ); + ) + .use_break_points(break_points); let num_instances = agg_circuit.num_instance(); let instances = agg_circuit.instances(); let proof = gen_evm_proof_shplonk(¶ms, &pk, agg_circuit, instances.clone()); diff --git a/snark-verifier-sdk/examples/n_as_witness.rs b/snark-verifier-sdk/examples/n_as_witness.rs index 3ee25f23..3561447f 100644 --- a/snark-verifier-sdk/examples/n_as_witness.rs +++ b/snark-verifier-sdk/examples/n_as_witness.rs @@ -1,4 +1,4 @@ -use halo2_base::gates::builder::CircuitBuilderStage; +use halo2_base::gates::circuit::CircuitBuilderStage; use halo2_base::halo2_proofs; use halo2_base::halo2_proofs::arithmetic::Field; use halo2_base::halo2_proofs::halo2curves::bn256::Fr; @@ -162,12 +162,11 @@ fn main() { let mut agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Keygen, AggregationConfigParams { degree: k, lookup_bits, ..Default::default() }, - None, ¶ms, vec![dummy_snark], VerifierUniversality::Full, ); - let agg_config = agg_circuit.config(Some(10)); + let agg_config = agg_circuit.calculate_params(Some(10)); let pk = gen_pk(¶ms, &agg_circuit, None); let break_points = agg_circuit.break_points(); @@ -177,11 +176,11 @@ fn main() { let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Prover, agg_config, - Some(break_points.clone()), ¶ms, vec![snark], VerifierUniversality::Full, - ); + ) + .use_break_points(break_points.clone()); let _snark = gen_snark_shplonk(¶ms, &pk, agg_circuit, None::<&str>); println!("snark with k = {k} success"); } diff --git a/snark-verifier-sdk/examples/range_check.rs b/snark-verifier-sdk/examples/range_check.rs index c9200df7..2beb5a78 100644 --- a/snark-verifier-sdk/examples/range_check.rs +++ b/snark-verifier-sdk/examples/range_check.rs @@ -1,11 +1,8 @@ use ark_std::{end_timer, start_timer}; -use halo2_base::gates::builder::{ - BaseConfigParams, CircuitBuilderStage, GateThreadBuilder, RangeWithInstanceCircuitBuilder, -}; -use halo2_base::gates::flex_gate::GateStrategy; +use halo2_base::gates::circuit::builder::BaseCircuitBuilder; +use halo2_base::gates::circuit::{BaseCircuitParams, CircuitBuilderStage}; +use halo2_base::gates::{GateInstructions, RangeInstructions}; use halo2_base::halo2_proofs::halo2curves::bn256::Fr; -use halo2_base::halo2_proofs::plonk::Circuit; -use halo2_base::safe_types::{GateInstructions, RangeChip, RangeInstructions}; use halo2_base::utils::fs::gen_srs; use itertools::Itertools; @@ -18,43 +15,33 @@ use snark_verifier_sdk::{ }; fn generate_circuit(k: u32) -> Snark { - let mut builder = GateThreadBuilder::new(false); - let ctx = builder.main(0); let lookup_bits = k as usize - 1; - let range = RangeChip::::default(lookup_bits); + let circuit_params = BaseCircuitParams { + k: k as usize, + num_advice_per_phase: vec![10], + num_lookup_advice_per_phase: vec![5], + num_fixed: 1, + lookup_bits: Some(lookup_bits), + num_instance_columns: 1, + }; + let mut builder = BaseCircuitBuilder::new(false).use_params(circuit_params); + let range = builder.range_chip(); + + let ctx = builder.main(0); let x = ctx.load_witness(Fr::from(14)); range.range_check(ctx, x, 2 * lookup_bits + 1); range.gate().add(ctx, x, x); - let circuit = RangeWithInstanceCircuitBuilder::::keygen( - builder.clone(), - BaseConfigParams { - strategy: GateStrategy::Vertical, - k: k as usize, - num_advice_per_phase: vec![1], - num_lookup_advice_per_phase: vec![1], - num_fixed: 1, - lookup_bits: Some(lookup_bits), - }, - vec![], - ); let params = gen_srs(k); - - let pk = gen_pk(¶ms, &circuit, None); - let breakpoints = circuit.break_points(); - - let circuit = RangeWithInstanceCircuitBuilder::::prover( - builder.clone(), - circuit.params(), - breakpoints, - vec![], - ); - gen_snark_shplonk(¶ms, &pk, circuit, None::<&str>) + // do not call calculate_params, we want to use fixed params + let pk = gen_pk(¶ms, &builder, None); + // builder now has break_point set + gen_snark_shplonk(¶ms, &pk, builder, None::<&str>) } fn main() { - let dummy_snark = generate_circuit(13); + let dummy_snark = generate_circuit(9); let k = 14u32; let lookup_bits = k as usize - 1; @@ -62,28 +49,27 @@ fn main() { let mut agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Keygen, AggregationConfigParams { degree: k, lookup_bits, ..Default::default() }, - None, ¶ms, vec![dummy_snark], VerifierUniversality::Full, ); - let agg_config = agg_circuit.config(Some(10)); + let agg_config = agg_circuit.calculate_params(Some(10)); let start0 = start_timer!(|| "gen vk & pk"); let pk = gen_pk(¶ms, &agg_circuit, None); end_timer!(start0); let break_points = agg_circuit.break_points(); - let snarks = (14..17).map(generate_circuit).collect_vec(); + let snarks = (10..16).map(generate_circuit).collect_vec(); for (i, snark) in snarks.into_iter().enumerate() { let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Prover, agg_config, - Some(break_points.clone()), ¶ms, vec![snark], VerifierUniversality::Full, - ); + ) + .use_break_points(break_points.clone()); let _snark = gen_snark_shplonk(¶ms, &pk, agg_circuit, None::<&str>); println!("snark {i} success"); } diff --git a/snark-verifier-sdk/examples/vkey_as_witness.rs b/snark-verifier-sdk/examples/vkey_as_witness.rs index a0eb30d2..ca066d80 100644 --- a/snark-verifier-sdk/examples/vkey_as_witness.rs +++ b/snark-verifier-sdk/examples/vkey_as_witness.rs @@ -1,6 +1,6 @@ use application::ComputeFlag; -use halo2_base::gates::builder::CircuitBuilderStage; +use halo2_base::gates::circuit::CircuitBuilderStage; use halo2_base::halo2_proofs; use halo2_base::halo2_proofs::arithmetic::Field; use halo2_base::halo2_proofs::halo2curves::bn256::Fr; @@ -157,12 +157,11 @@ fn main() { let mut agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Keygen, AggregationConfigParams { degree: k, lookup_bits, ..Default::default() }, - None, ¶ms, vec![dummy_snark], VerifierUniversality::PreprocessedAsWitness, ); - let agg_config = agg_circuit.config(Some(10)); + let agg_config = agg_circuit.calculate_params(Some(10)); let pk = gen_pk(¶ms, &agg_circuit, None); let break_points = agg_circuit.break_points(); @@ -173,11 +172,11 @@ fn main() { let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Prover, agg_config, - Some(break_points.clone()), ¶ms, vec![snark], VerifierUniversality::PreprocessedAsWitness, - ); + ) + .use_break_points(break_points.clone()); let _snark = gen_snark_shplonk(¶ms, &pk, agg_circuit, None::<&str>); println!("snark {i} success"); } diff --git a/snark-verifier-sdk/src/halo2/aggregation.rs b/snark-verifier-sdk/src/halo2/aggregation.rs index 60674a6c..f24dc96e 100644 --- a/snark-verifier-sdk/src/halo2/aggregation.rs +++ b/snark-verifier-sdk/src/halo2/aggregation.rs @@ -1,13 +1,12 @@ use super::PlonkSuccinctVerifier; use crate::{BITS, LIMBS}; +use getset::Getters; use halo2_base::{ gates::{ - builder::{ - BaseConfigParams, CircuitBuilderStage, GateThreadBuilder, MultiPhaseThreadBreakPoints, - PublicBaseConfig, RangeWithInstanceCircuitBuilder, + circuit::{ + builder::BaseCircuitBuilder, BaseCircuitParams, BaseConfig, CircuitBuilderStage, }, - flex_gate::GateStrategy, - RangeChip, + flex_gate::MultiPhaseThreadBreakPoints, }, halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, @@ -35,7 +34,7 @@ use snark_verifier::{ }, verifier::SnarkVerifier, }; -use std::{fs::File, path::Path, rc::Rc}; +use std::{fs::File, mem, path::Path, rc::Rc}; use super::{CircuitExt, PoseidonTranscript, Snark, POSEIDON_SPEC}; @@ -222,23 +221,23 @@ impl AggregationConfigParams { } } -impl From for BaseConfigParams { +impl From for BaseCircuitParams { fn from(params: AggregationConfigParams) -> Self { - BaseConfigParams { - strategy: GateStrategy::Vertical, + BaseCircuitParams { k: params.degree as usize, num_advice_per_phase: vec![params.num_advice], num_lookup_advice_per_phase: vec![params.num_lookup_advice], num_fixed: params.num_fixed, lookup_bits: Some(params.lookup_bits), + num_instance_columns: 1, } } } -impl TryFrom<&BaseConfigParams> for AggregationConfigParams { +impl TryFrom<&BaseCircuitParams> for AggregationConfigParams { type Error = &'static str; - fn try_from(params: &BaseConfigParams) -> Result { + fn try_from(params: &BaseCircuitParams) -> Result { if params.num_advice_per_phase.iter().skip(1).any(|&n| n != 0) { return Err("AggregationConfigParams only supports 1 phase"); } @@ -248,6 +247,9 @@ impl TryFrom<&BaseConfigParams> for AggregationConfigParams { if params.lookup_bits.is_none() { return Err("AggregationConfigParams requires lookup_bits"); } + if params.num_instance_columns != 1 { + return Err("AggregationConfigParams only supports 1 instance column"); + } Ok(Self { degree: params.k as u32, num_advice: params.num_advice_per_phase[0], @@ -258,42 +260,29 @@ impl TryFrom<&BaseConfigParams> for AggregationConfigParams { } } -impl TryFrom for AggregationConfigParams { +impl TryFrom for AggregationConfigParams { type Error = &'static str; - fn try_from(value: BaseConfigParams) -> Result { + fn try_from(value: BaseCircuitParams) -> Result { Self::try_from(&value) } } -/// Holds virtual contexts for the cells used to verify a collection of snarks -#[derive(Clone, Debug)] -pub struct AggregationCtxBuilder { - /// Virtual region with virtual contexts (columns) - pub builder: GateThreadBuilder, - /// The limbs of the pair of elliptic curve points that need to be verified in a final pairing check. - pub accumulator: Vec>, - // the public instances from previous snarks that were aggregated - pub previous_instances: Vec>>, - /// This returns the assigned `preprocessed_digest` (vkey), optional `transcript_initial_state`, `domain.n` (optional), and `omega` (optional) values as a vector of assigned values, one for each aggregated snark. - /// These can then be exposed as public instances. - /// - /// This is only useful if preprocessed digest is loaded as witness (i.e., `universality != None`), so we set it to `None` if `universality == None`. - pub preprocessed_digests: Option>>>, -} - -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Getters)] pub struct AggregationCircuit { - pub inner: RangeWithInstanceCircuitBuilder, + /// Circuit builder consisting of virtual region managers + pub builder: BaseCircuitBuilder, // the public instances from previous snarks that were aggregated, now collected as PRIVATE assigned values // the user can optionally append these to `inner.assigned_instances` to expose them - pub previous_instances: Vec>>, + #[getset(get = "pub")] + previous_instances: Vec>>, /// This returns the assigned `preprocessed_digest` (vkey), optional `transcript_initial_state`, `domain.n` (optional), and `omega` (optional) values as a vector of assigned values, one for each aggregated snark. /// These can then be exposed as public instances. /// /// This is only useful if preprocessed digest is loaded as witness (i.e., `universality != None`), so we set it to `None` if `universality == None`. - pub preprocessed_digests: Option>>>, - // accumulation scheme proof, private input + #[getset(get = "pub")] + preprocessed_digests: Option>>>, + // accumulation scheme proof, no longer used // pub as_proof: Vec, } @@ -320,23 +309,23 @@ pub trait Halo2KzgAccumulationScheme<'a> = PolynomialCommitmentScheme< VerifyingKey = KzgAsVerifyingKey, > + AccumulationSchemeProver>; -impl AggregationCtxBuilder { - /// Given snarks, this runs the `GateThreadBuilder` to verify all the snarks. +impl AggregationCircuit { + /// Given snarks, this creates `BaseCircuitBuilder` and populates the circuit builder with the virtual cells and constraints necessary to verify all the snarks. /// - /// Also returns the limbs of the pair of elliptic curve points, referred to as the `accumulator`, that need to be verified in a final pairing check. + /// By default, the returned circuit has public instances equal to the limbs of the pair of elliptic curve points, referred to as the `accumulator`, that need to be verified in a final pairing check. /// /// # Universality /// - If `universality` is not `None`, then the verifying keys of each snark in `snarks` is loaded as a witness in the circuit. /// - Moreover, if `universality` is `Full`, then the number of rows `n` of each snark in `snarks` is also loaded as a witness. In this case the generator `omega` of the order `n` multiplicative subgroup of `F` is also loaded as a witness. - /// - By default, these witnesses are _private_ and returned in `self.preprocessed_ + /// - By default, these witnesses are _private_ and returned in `self.preprocessed_digests /// - The user can optionally modify the circuit after calling this function to add more instances to `assigned_instances` to expose. /// /// # Warning /// Will fail silently if `snarks` were created using a different multi-open scheme than `AS` /// where `AS` can be either [`crate::SHPLONK`] or [`crate::GWC`] (for original PLONK multi-open scheme) pub fn new( - witness_gen_only: bool, - lookup_bits: usize, + stage: CircuitBuilderStage, + config_params: AggregationConfigParams, params: &ParamsKZG, snarks: impl IntoIterator, universality: VerifierUniversality, @@ -378,14 +367,19 @@ impl AggregationCtxBuilder { (accumulator, transcript_write.finalize()) }; - // create thread builder and run aggregation witness gen - let builder = GateThreadBuilder::new(witness_gen_only); + let mut builder = BaseCircuitBuilder::from_stage(stage).use_params(config_params.into()); // create halo2loader - let range = RangeChip::::default(lookup_bits); + let range = builder.range_chip(); let fp_chip = FpChip::::new(&range, BITS, LIMBS); let ecc_chip = BaseFieldEccChip::new(&fp_chip); - let loader = Halo2Loader::new(ecc_chip, builder); - + // Take the phase 0 pool from `builder`; it needs to be owned by loader. + // We put it back later (below), so it should have same effect as just mutating `builder.pool(0)`. + let pool = mem::take(builder.pool(0)); + // range_chip has shared reference to LookupAnyManager, with shared CopyConstraintManager + // pool has shared reference to CopyConstraintManager + let loader = Halo2Loader::new(ecc_chip, pool); + + // run witness and copy constraint generation let SnarkAggregationWitness { previous_instances, accumulator, preprocessed_digests } = aggregate::(&svk, &loader, &snarks, as_proof.as_slice(), universality); let lhs = accumulator.lhs.assigned(); @@ -409,76 +403,16 @@ impl AggregationCtxBuilder { assert_eq!(lhs, rhs.value()); } } - - let builder = loader.take_ctx(); - Self { builder, accumulator, previous_instances, preprocessed_digests } - } -} - -impl AggregationCircuit { - /// Given snarks, this creates a circuit and runs the `GateThreadBuilder` to verify all the snarks. - /// By default, the returned circuit has public instances equal to the limbs of the pair of elliptic curve points, referred to as the `accumulator`, that need to be verified in a final pairing check. - /// - /// See [`AggregationCtxBuilder`] for more details. - /// - /// The user can optionally modify the circuit after calling this function to add more instances to `assigned_instances` to expose. - /// - /// Warning: will fail silently if `snarks` were created using a different multi-open scheme than `AS` - /// where `AS` can be either [`crate::SHPLONK`] or [`crate::GWC`] (for original PLONK multi-open scheme) - pub fn new( - stage: CircuitBuilderStage, - agg_config: AggregationConfigParams, - break_points: Option, - params: &ParamsKZG, - snarks: impl IntoIterator, - universality: VerifierUniversality, - ) -> Self - where - AS: for<'a> Halo2KzgAccumulationScheme<'a>, - { - let AggregationCtxBuilder { - builder, - accumulator, - previous_instances, - preprocessed_digests, - } = AggregationCtxBuilder::new::( - stage == CircuitBuilderStage::Prover, - agg_config.lookup_bits, - params, - snarks, - universality, + // put back `pool` into `builder` + *builder.pool(0) = loader.take_ctx(); + assert_eq!( + builder.assigned_instances.len(), + 1, + "AggregationCircuit must have exactly 1 instance column" ); - let inner = RangeWithInstanceCircuitBuilder::from_stage( - stage, - builder, - agg_config.into(), - break_points, - accumulator, - ); - Self { inner, previous_instances, preprocessed_digests } - } - - pub fn public( - stage: CircuitBuilderStage, - agg_config: AggregationConfigParams, - break_points: Option, - params: &ParamsKZG, - snarks: impl IntoIterator, - has_prev_accumulator: bool, - ) -> Self - where - AS: for<'a> Halo2KzgAccumulationScheme<'a>, - { - let mut private = Self::new::( - stage, - agg_config, - break_points, - params, - snarks, - VerifierUniversality::None, - ); - private.expose_previous_instances(has_prev_accumulator); - private + // expose accumulator as public instances + builder.assigned_instances[0] = accumulator; + Self { builder, previous_instances, preprocessed_digests } } /// Re-expose the previous public instances of aggregated snarks again. @@ -487,49 +421,72 @@ impl AggregationCircuit { pub fn expose_previous_instances(&mut self, has_prev_accumulator: bool) { let start = (has_prev_accumulator as usize) * 4 * LIMBS; for prev in self.previous_instances.iter() { - self.inner.assigned_instances.extend_from_slice(&prev[start..]); + self.builder.assigned_instances[0].extend_from_slice(&prev[start..]); } } - /// Auto-configure the circuit and change the circuit's internal configuration parameters. - pub fn config(&mut self, minimum_rows: Option) -> AggregationConfigParams { - self.inner.config(minimum_rows).try_into().unwrap() + /// The log_2 size of the lookup table + pub fn lookup_bits(&self) -> usize { + self.builder.config_params.lookup_bits.unwrap() + } + + /// Set config params + pub fn set_params(&mut self, params: AggregationConfigParams) { + self.builder.set_params(params.into()); } + /// Returns new with config params + pub fn use_params(mut self, params: AggregationConfigParams) -> Self { + self.set_params(params); + self + } + + /// The break points of the circuit. pub fn break_points(&self) -> MultiPhaseThreadBreakPoints { - self.inner.break_points() + self.builder.break_points() + } + + /// Sets the break points of the circuit. + pub fn set_break_points(&mut self, break_points: MultiPhaseThreadBreakPoints) { + self.builder.set_break_points(break_points); } - pub fn instance_count(&self) -> usize { - self.inner.instance_count() + /// Returns new with break points + pub fn use_break_points(mut self, break_points: MultiPhaseThreadBreakPoints) -> Self { + self.set_break_points(break_points); + self } - pub fn instance(&self) -> Vec { - self.inner.instance() + /// Auto-configure the circuit and change the circuit's internal configuration parameters. + pub fn calculate_params(&mut self, minimum_rows: Option) -> AggregationConfigParams { + self.builder.calculate_params(minimum_rows).try_into().unwrap() } } -impl CircuitExt for RangeWithInstanceCircuitBuilder { +impl CircuitExt for BaseCircuitBuilder { fn num_instance(&self) -> Vec { - vec![self.instance_count()] + self.assigned_instances.iter().map(|instances| instances.len()).collect() } fn instances(&self) -> Vec> { - vec![self.instance()] + self.assigned_instances + .iter() + .map(|instances| instances.iter().map(|v| *v.value()).collect()) + .collect() } fn selectors(config: &Self::Config) -> Vec { - config.base.gate().basic_gates[0].iter().map(|gate| gate.q_enable).collect() + config.gate().basic_gates[0].iter().map(|gate| gate.q_enable).collect() } } impl Circuit for AggregationCircuit { - type Config = PublicBaseConfig; + type Config = BaseConfig; type FloorPlanner = SimpleFloorPlanner; type Params = AggregationConfigParams; fn params(&self) -> Self::Params { - (&self.inner.circuit.0.config_params).try_into().unwrap() + (&self.builder.config_params).try_into().unwrap() } fn without_witnesses(&self) -> Self { @@ -540,7 +497,7 @@ impl Circuit for AggregationCircuit { meta: &mut ConstraintSystem, params: Self::Params, ) -> Self::Config { - RangeWithInstanceCircuitBuilder::configure_with_params(meta, params.into()) + BaseCircuitBuilder::configure_with_params(meta, params.into()) } fn configure(_: &mut ConstraintSystem) -> Self::Config { @@ -552,17 +509,17 @@ impl Circuit for AggregationCircuit { config: Self::Config, layouter: impl Layouter, ) -> Result<(), plonk::Error> { - self.inner.synthesize(config, layouter) + self.builder.synthesize(config, layouter) } } impl CircuitExt for AggregationCircuit { fn num_instance(&self) -> Vec { - self.inner.num_instance() + self.builder.num_instance() } fn instances(&self) -> Vec> { - self.inner.instances() + self.builder.instances() } fn accumulator_indices() -> Option> { @@ -570,7 +527,7 @@ impl CircuitExt for AggregationCircuit { } fn selectors(config: &Self::Config) -> Vec { - RangeWithInstanceCircuitBuilder::selectors(config) + BaseCircuitBuilder::selectors(config) } } diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index f4c4f4af..fbc40c85 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snark-verifier" -version = "0.1.3" +version = "0.1.4" edition = "2021" [dependencies] diff --git a/snark-verifier/examples/evm-verifier-with-accumulator.rs b/snark-verifier/examples/evm-verifier-with-accumulator.rs index 650598aa..645c71fd 100644 --- a/snark-verifier/examples/evm-verifier-with-accumulator.rs +++ b/snark-verifier/examples/evm-verifier-with-accumulator.rs @@ -1,6 +1,6 @@ use aggregation::{AggregationCircuit, AggregationConfigParams}; use halo2_base::{ - gates::builder::{BaseConfigParams, CircuitBuilderStage}, + gates::circuit::{BaseCircuitParams, CircuitBuilderStage}, halo2_proofs, utils::fs::gen_srs, }; @@ -202,18 +202,11 @@ mod application { mod aggregation { use crate::PlonkSuccinctVerifier; - use super::halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner}, - plonk::{self, Circuit}, - }; use super::{As, BITS, LIMBS}; use super::{Fr, G1Affine}; use halo2_base::gates::{ - builder::{ - BaseConfigParams, CircuitBuilderStage, GateThreadBuilder, MultiPhaseThreadBreakPoints, - PublicBaseConfig, RangeWithInstanceCircuitBuilder, - }, - RangeChip, + circuit::{builder::BaseCircuitBuilder, BaseCircuitParams, CircuitBuilderStage}, + flex_gate::MultiPhaseThreadBreakPoints, }; use halo2_ecc::bn254::FpChip; use itertools::Itertools; @@ -228,7 +221,7 @@ mod aggregation { util::arithmetic::fe_to_limbs, verifier::{plonk::PlonkProtocol, SnarkVerifier}, }; - use std::rc::Rc; + use std::{mem, rc::Rc}; const T: usize = 3; const RATE: usize = 2; @@ -311,14 +304,14 @@ mod aggregation { #[derive(Clone, Debug)] pub struct AggregationCircuit { - pub inner: RangeWithInstanceCircuitBuilder, + pub inner: BaseCircuitBuilder, pub as_proof: Vec, } impl AggregationCircuit { pub fn new( stage: CircuitBuilderStage, - config_params: BaseConfigParams, + circuit_params: BaseCircuitParams, break_points: Option, params_g0: G1Affine, snarks: impl IntoIterator, @@ -354,14 +347,15 @@ mod aggregation { (accumulator, transcript.finalize()) }; - // create thread builder and run aggregation witness gen - let builder = GateThreadBuilder::from_stage(stage); + let mut builder = BaseCircuitBuilder::from_stage(stage).use_params(circuit_params); // create halo2loader - let range = RangeChip::::default(config_params.lookup_bits.unwrap()); + let range = builder.range_chip(); let fp_chip = FpChip::::new(&range, BITS, LIMBS); let ecc_chip = BaseFieldEccChip::new(&fp_chip); - let loader = Halo2Loader::new(ecc_chip, builder); + let pool = mem::take(builder.pool(0)); + let loader = Halo2Loader::new(ecc_chip, pool); + // witness generation let KzgAccumulator { lhs, rhs } = aggregate(&svk, &loader, &snarks, as_proof.as_slice()); let lhs = lhs.assigned(); @@ -386,30 +380,12 @@ mod aggregation { } } - let builder = loader.take_ctx(); - let inner = RangeWithInstanceCircuitBuilder::from_stage( - stage, - builder, - config_params, - break_points, - assigned_instances, - ); - Self { inner, as_proof } - } - - pub fn config( - &self, - k: u32, - minimum_rows: Option, - lookup_bits: usize, - ) -> BaseConfigParams { - let mut params = self.inner.circuit.0.builder.borrow().config(k as usize, minimum_rows); - params.lookup_bits = Some(lookup_bits); - params - } - - pub fn break_points(&self) -> MultiPhaseThreadBreakPoints { - self.inner.circuit.0.break_points.borrow().clone() + *builder.pool(0) = loader.take_ctx(); + builder.assigned_instances[0] = assigned_instances; + if let Some(break_points) = break_points { + builder.set_break_points(break_points); + } + Self { inner: builder, as_proof } } pub fn num_instance() -> Vec { @@ -418,46 +394,17 @@ mod aggregation { } pub fn instances(&self) -> Vec> { - vec![self.inner.assigned_instances.iter().map(|v| *v.value()).collect_vec()] + self.inner + .assigned_instances + .iter() + .map(|v| v.iter().map(|v| *v.value()).collect_vec()) + .collect() } pub fn accumulator_indices() -> Vec<(usize, usize)> { (0..4 * LIMBS).map(|idx| (0, idx)).collect() } } - - impl Circuit for AggregationCircuit { - type Config = PublicBaseConfig; - type FloorPlanner = SimpleFloorPlanner; - type Params = BaseConfigParams; - - fn params(&self) -> Self::Params { - self.inner.circuit.params() - } - - fn configure_with_params( - meta: &mut plonk::ConstraintSystem, - params: Self::Params, - ) -> Self::Config { - RangeWithInstanceCircuitBuilder::configure_with_params(meta, params) - } - - fn without_witnesses(&self) -> Self { - unimplemented!() - } - - fn configure(_: &mut plonk::ConstraintSystem) -> Self::Config { - unimplemented!() - } - - fn synthesize( - &self, - config: Self::Config, - layouter: impl Layouter, - ) -> Result<(), plonk::Error> { - self.inner.synthesize(config, layouter) - } - } } fn gen_pk>(params: &ParamsKZG, circuit: &C) -> ProvingKey { @@ -573,33 +520,32 @@ fn main() { File::open(path).unwrap_or_else(|e| panic!("{path} does not exist: {e:?}")), ) .unwrap(); - let mut config_params = BaseConfigParams { + let mut circuit_params = BaseCircuitParams { k: agg_config.degree as usize, - strategy: Default::default(), num_advice_per_phase: vec![agg_config.num_advice], num_lookup_advice_per_phase: vec![agg_config.num_lookup_advice], num_fixed: agg_config.num_fixed, lookup_bits: Some(agg_config.lookup_bits), + num_instance_columns: 1, }; let mut agg_circuit = AggregationCircuit::new( CircuitBuilderStage::Mock, - config_params, + circuit_params, None, params_app.get_g()[0], snarks.clone(), ); - config_params = agg_circuit.config(agg_config.degree, Some(6), agg_config.lookup_bits); - agg_circuit.inner.circuit.0.config_params = config_params.clone(); + circuit_params = agg_circuit.inner.calculate_params(Some(9)); #[cfg(debug_assertions)] { - MockProver::run(agg_config.degree, &agg_circuit, agg_circuit.instances()) + MockProver::run(agg_config.degree, &agg_circuit.inner, agg_circuit.instances()) .unwrap() .assert_satisfied(); println!("mock prover passed"); } let params = gen_srs(agg_config.degree); - let pk = gen_pk(¶ms, &agg_circuit); + let pk = gen_pk(¶ms, &agg_circuit.inner); let deployment_code = gen_aggregation_evm_verifier( ¶ms, pk.get_vk(), @@ -607,12 +553,12 @@ fn main() { aggregation::AggregationCircuit::accumulator_indices(), ); - let break_points = agg_circuit.break_points(); + let break_points = agg_circuit.inner.break_points(); drop(agg_circuit); let agg_circuit = AggregationCircuit::new( CircuitBuilderStage::Prover, - config_params, + circuit_params, Some(break_points), params_app.get_g()[0], snarks, @@ -621,7 +567,7 @@ fn main() { let proof = gen_proof::<_, _, EvmTranscript, EvmTranscript>( ¶ms, &pk, - agg_circuit, + agg_circuit.inner, instances.clone(), ); evm_verify(deployment_code, instances, proof); diff --git a/snark-verifier/examples/recursion.rs b/snark-verifier/examples/recursion.rs index 9c9b169a..da34cb82 100644 --- a/snark-verifier/examples/recursion.rs +++ b/snark-verifier/examples/recursion.rs @@ -2,10 +2,8 @@ use ark_std::{end_timer, start_timer}; use common::*; -use halo2_base::gates::builder::BaseConfigParams; -use halo2_base::gates::flex_gate::GateStrategy; -use halo2_base::halo2_proofs; use halo2_base::utils::fs::gen_srs; +use halo2_base::{gates::circuit::BaseCircuitParams, halo2_proofs}; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, dev::MockProver, @@ -342,10 +340,12 @@ mod application { } mod recursion { + use std::mem; + use halo2_base::{ gates::{ - builder::{GateThreadBuilder, PublicBaseConfig, RangeWithInstanceCircuitBuilder}, - GateInstructions, RangeChip, RangeInstructions, + circuit::{builder::BaseCircuitBuilder, BaseCircuitParams, BaseConfig}, + GateInstructions, RangeInstructions, }, AssignedValue, }; @@ -426,7 +426,7 @@ mod recursion { .zip([rhs.lhs.assigned(), rhs.rhs.assigned()].iter()) .map(|(lhs, rhs)| { loader.ecc_chip().select( - loader.ctx_mut().main(0), + loader.ctx_mut().main(), EcPoint::clone(lhs), EcPoint::clone(rhs), *condition, @@ -471,9 +471,8 @@ mod recursion { round: usize, instances: Vec, as_proof: Vec, - lookup_bits: usize, - inner: RangeWithInstanceCircuitBuilder, + inner: BaseCircuitBuilder, } impl RecursionCircuit { @@ -489,7 +488,7 @@ mod recursion { initial_state: Fr, state: Fr, round: usize, - config_params: BaseConfigParams, + config_params: BaseCircuitParams, ) -> Self { let svk = params.get_g()[0].into(); let default_accumulator = KzgAccumulator::new(params.get_g()[1], params.get_g()[0]); @@ -544,42 +543,30 @@ mod recursion { .chain([preprocessed_digest, initial_state, state, Fr::from(round as u64)]) .collect(); - let builder = GateThreadBuilder::mock(); - let lookup_bits = config_params.lookup_bits.unwrap(); - let inner = RangeWithInstanceCircuitBuilder::mock(builder, config_params, vec![]); - let mut circuit = Self { - svk, - default_accumulator, - app, - previous, - round, - instances, - as_proof, - inner, - lookup_bits, - }; + let inner = BaseCircuitBuilder::new(false).use_params(config_params); + let mut circuit = + Self { svk, default_accumulator, app, previous, round, instances, as_proof, inner }; circuit.build(); circuit } fn build(&mut self) { - let range = RangeChip::::default(self.lookup_bits); + let range = self.inner.range_chip(); let main_gate = range.gate(); - let mut builder = GateThreadBuilder::mock(); - let ctx = &mut builder; + let pool = self.inner.pool(0); let [preprocessed_digest, initial_state, state, round] = [ self.instances[Self::PREPROCESSED_DIGEST_ROW], self.instances[Self::INITIAL_STATE_ROW], self.instances[Self::STATE_ROW], self.instances[Self::ROUND_ROW], ] - .map(|instance| main_gate.assign_integer(ctx, instance)); - let first_round = main_gate.is_zero(ctx.main(0), round); - let not_first_round = main_gate.not(ctx.main(0), first_round); + .map(|instance| main_gate.assign_integer(pool, instance)); + let first_round = main_gate.is_zero(pool.main(), round); + let not_first_round = main_gate.not(pool.main(), first_round); let fp_chip = FpChip::::new(&range, BITS, LIMBS); let ecc_chip = BaseFieldEccChip::new(&fp_chip); - let loader = Halo2Loader::new(ecc_chip, builder); + let loader = Halo2Loader::new(ecc_chip, mem::take(self.inner.pool(0))); let (mut app_instances, app_accumulators) = succinct_verify(&self.svk, &loader, &self.app, None); let (mut previous_instances, previous_accumulators) = @@ -610,8 +597,8 @@ mod recursion { let app_instances = app_instances.pop().unwrap(); let previous_instances = previous_instances.pop().unwrap(); - let mut builder = loader.take_ctx(); - let ctx = builder.main(0); + let mut pool = loader.take_ctx(); + let ctx = pool.main(); for (lhs, rhs) in [ // Propagate preprocessed_digest ( @@ -640,9 +627,9 @@ mod recursion { ] { ctx.constrain_equal(lhs, rhs); } - *self.inner.circuit.0.builder.borrow_mut() = builder; + *self.inner.pool(0) = pool; - self.inner.assigned_instances.extend( + self.inner.assigned_instances[0].extend( [lhs.x(), lhs.y(), rhs.x(), rhs.y()] .into_iter() .flat_map(|coordinate| coordinate.limbs()) @@ -654,7 +641,7 @@ mod recursion { fn initial_snark( params: &ParamsKZG, vk: Option<&VerifyingKey>, - config_params: BaseConfigParams, + config_params: BaseCircuitParams, ) -> Snark { let mut snark = gen_dummy_snark::(params, vk, config_params); let g = params.get_g(); @@ -685,12 +672,12 @@ mod recursion { } impl Circuit for RecursionCircuit { - type Config = PublicBaseConfig; + type Config = BaseConfig; type FloorPlanner = SimpleFloorPlanner; - type Params = BaseConfigParams; + type Params = BaseCircuitParams; fn params(&self) -> Self::Params { - self.inner.circuit.params() + self.inner.params() } fn without_witnesses(&self) -> Self { @@ -701,7 +688,7 @@ mod recursion { meta: &mut ConstraintSystem, params: Self::Params, ) -> Self::Config { - RangeWithInstanceCircuitBuilder::configure_with_params(meta, params) + BaseCircuitBuilder::configure_with_params(meta, params) } fn configure(_: &mut ConstraintSystem) -> Self::Config { @@ -732,7 +719,7 @@ mod recursion { } fn selectors(config: &Self::Config) -> Vec { - config.base.gate().basic_gates[0].iter().map(|gate| gate.q_enable).collect() + config.gate().basic_gates[0].iter().map(|gate| gate.q_enable).collect() } } @@ -740,7 +727,7 @@ mod recursion { recursion_params: &ParamsKZG, app_params: &ParamsKZG, app_vk: &VerifyingKey, - recursion_config: BaseConfigParams, + recursion_config: BaseCircuitParams, app_config: ConcreteCircuit::Params, ) -> ProvingKey where @@ -768,7 +755,7 @@ mod recursion { recursion_pk: &ProvingKey, initial_state: Fr, inputs: Vec, - config_params: BaseConfigParams, + config_params: BaseCircuitParams, ) -> (Fr, Snark) { let mut state = initial_state; let mut app = ConcreteCircuit::new(state); @@ -804,13 +791,13 @@ fn main() { serde_json::from_reader(fs::File::open("configs/example_recursion.json").unwrap()).unwrap(); let k = recursion_config.degree; let recursion_params = gen_srs(k); - let config_params = BaseConfigParams { - strategy: GateStrategy::Vertical, + let config_params = BaseCircuitParams { k: k as usize, num_advice_per_phase: vec![recursion_config.num_advice], num_lookup_advice_per_phase: vec![recursion_config.num_lookup_advice], num_fixed: recursion_config.num_fixed, lookup_bits: Some(recursion_config.lookup_bits), + num_instance_columns: 1, }; let app_pk = gen_pk(&app_params, &application::Square::default()); diff --git a/snark-verifier/src/loader/halo2/shim.rs b/snark-verifier/src/loader/halo2/shim.rs index 49bbad41..80d5eae2 100644 --- a/snark-verifier/src/loader/halo2/shim.rs +++ b/snark-verifier/src/loader/halo2/shim.rs @@ -143,9 +143,10 @@ mod halo2_lib { loader::halo2::{EccInstructions, IntegerInstructions}, util::arithmetic::{CurveAffine, PrimeField}, }; + use halo2_base::gates::flex_gate::threads::SinglePhaseCoreManager; use halo2_base::{ self, - gates::{builder::GateThreadBuilder, GateChip, GateInstructions, RangeInstructions}, + gates::{GateChip, GateInstructions, RangeInstructions}, utils::BigPrimeField, AssignedValue, QuantumCell::{Constant, Existing}, @@ -161,16 +162,16 @@ mod halo2_lib { type AssignedEcPoint = EcPoint<::ScalarExt, AssignedInteger>; impl IntegerInstructions for GateChip { - type Context = GateThreadBuilder; + type Context = SinglePhaseCoreManager; type AssignedCell = AssignedValue; type AssignedInteger = AssignedValue; fn assign_integer(&self, ctx: &mut Self::Context, integer: F) -> Self::AssignedInteger { - ctx.main(0).load_witness(integer) + ctx.main().load_witness(integer) } fn assign_constant(&self, ctx: &mut Self::Context, integer: F) -> Self::AssignedInteger { - ctx.main(0).load_constant(integer) + ctx.main().load_constant(integer) } fn sum_with_coeff_and_const( @@ -187,7 +188,7 @@ mod halo2_lib { } a.extend(values.iter().map(|(_, a)| Existing(*a.deref()))); b.extend(values.iter().map(|(c, _)| Constant(*c))); - self.inner_product(ctx.main(0), a, b) + self.inner_product(ctx.main(), a, b) } fn sum_products_with_coeff_and_const( @@ -201,9 +202,9 @@ mod halo2_lib { constant: F, ) -> Self::AssignedInteger { match values.len() { - 0 => ctx.main(0).load_constant(constant), + 0 => ctx.main().load_constant(constant), _ => self.sum_products_with_coeff_and_var( - ctx.main(0), + ctx.main(), values.iter().map(|(c, a, b)| (*c, Existing(*a.deref()), Existing(*b.deref()))), Constant(constant), ), @@ -216,11 +217,11 @@ mod halo2_lib { a: &Self::AssignedInteger, b: &Self::AssignedInteger, ) -> Self::AssignedInteger { - GateInstructions::sub(self, ctx.main(0), Existing(*a), Existing(*b)) + GateInstructions::sub(self, ctx.main(), Existing(*a), Existing(*b)) } fn neg(&self, ctx: &mut Self::Context, a: &Self::AssignedInteger) -> Self::AssignedInteger { - GateInstructions::neg(self, ctx.main(0), Existing(*a)) + GateInstructions::neg(self, ctx.main(), Existing(*a)) } fn invert( @@ -229,9 +230,9 @@ mod halo2_lib { a: &Self::AssignedInteger, ) -> Self::AssignedInteger { // make sure scalar != 0 - let is_zero = self.is_zero(ctx.main(0), *a); - self.assert_is_const(ctx.main(0), &is_zero, &F::ZERO); - GateInstructions::div_unsafe(self, ctx.main(0), Constant(F::ONE), Existing(*a)) + let is_zero = self.is_zero(ctx.main(), *a); + self.assert_is_const(ctx.main(), &is_zero, &F::ZERO); + GateInstructions::div_unsafe(self, ctx.main(), Constant(F::ONE), Existing(*a)) } fn assert_equal( @@ -240,7 +241,7 @@ mod halo2_lib { a: &Self::AssignedInteger, b: &Self::AssignedInteger, ) { - ctx.main(0).constrain_equal(a, b); + ctx.main().constrain_equal(a, b); } fn pow_var( @@ -250,7 +251,7 @@ mod halo2_lib { exponent: &Self::AssignedInteger, max_bits: usize, ) -> Self::AssignedInteger { - GateInstructions::pow_var(self, ctx.main(0), *base, *exponent, max_bits) + GateInstructions::pow_var(self, ctx.main(), *base, *exponent, max_bits) } } @@ -259,7 +260,7 @@ mod halo2_lib { C::ScalarExt: BigPrimeField, C::Base: BigPrimeField, { - type Context = GateThreadBuilder; + type Context = SinglePhaseCoreManager; type ScalarChip = GateChip; type AssignedCell = AssignedValue; type AssignedScalar = AssignedValue; @@ -270,11 +271,11 @@ mod halo2_lib { } fn assign_constant(&self, ctx: &mut Self::Context, point: C) -> Self::AssignedEcPoint { - self.assign_constant_point(ctx.main(0), point) + self.assign_constant_point(ctx.main(), point) } fn assign_point(&self, ctx: &mut Self::Context, point: C) -> Self::AssignedEcPoint { - self.assign_point(ctx.main(0), point) + self.assign_point(ctx.main(), point) } fn sum_with_const( @@ -290,7 +291,7 @@ mod halo2_lib { Some(constant) }; self.sum::( - ctx.main(0), + ctx.main(), constant.into_iter().chain(values.iter().map(|v| v.deref().clone())), ) } @@ -346,7 +347,7 @@ mod halo2_lib { a: &Self::AssignedEcPoint, b: &Self::AssignedEcPoint, ) { - self.assert_equal(ctx.main(0), a.clone(), b.clone()); + self.assert_equal(ctx.main(), a.clone(), b.clone()); } } } diff --git a/snark-verifier/src/pcs/kzg/accumulator.rs b/snark-verifier/src/pcs/kzg/accumulator.rs index 423ae7d5..37cb493f 100644 --- a/snark-verifier/src/pcs/kzg/accumulator.rs +++ b/snark-verifier/src/pcs/kzg/accumulator.rs @@ -220,7 +220,7 @@ mod halo2 { assert_eq!(limbs.len(), 2 * LIMBS); let ec_point = self.assign_point::( - ctx.main(0), + ctx.main(), ec_point_from_limbs::<_, LIMBS, BITS>( &limbs.iter().map(|limb| limb.value()).collect_vec(), ), @@ -230,7 +230,7 @@ mod halo2 { .iter() .zip_eq(iter::empty().chain(ec_point.x().limbs()).chain(ec_point.y().limbs())) { - ctx.main(0).constrain_equal(src, dst); + ctx.main().constrain_equal(src, dst); } ec_point From 10ef300fbaebaad80d9e71b74cff4ad1d6c6e476 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Fri, 1 Sep 2023 11:28:40 -0600 Subject: [PATCH 11/19] feat: load `k` as witness and compute `n = 2^k` and `omega` from `k` (#30) * feat: load `k` as witness and compute `n = 2^k` and `omega` from `k` Removes need to make `omega` a public output in universal verifier. * fix: bit_length --- .../{n_as_witness.rs => k_as_witness.rs} | 0 snark-verifier-sdk/src/halo2/aggregation.rs | 61 ++++++++++--------- snark-verifier/src/verifier/plonk/protocol.rs | 28 ++++++--- 3 files changed, 52 insertions(+), 37 deletions(-) rename snark-verifier-sdk/examples/{n_as_witness.rs => k_as_witness.rs} (100%) diff --git a/snark-verifier-sdk/examples/n_as_witness.rs b/snark-verifier-sdk/examples/k_as_witness.rs similarity index 100% rename from snark-verifier-sdk/examples/n_as_witness.rs rename to snark-verifier-sdk/examples/k_as_witness.rs diff --git a/snark-verifier-sdk/src/halo2/aggregation.rs b/snark-verifier-sdk/src/halo2/aggregation.rs index f24dc96e..690a64fc 100644 --- a/snark-verifier-sdk/src/halo2/aggregation.rs +++ b/snark-verifier-sdk/src/halo2/aggregation.rs @@ -42,14 +42,20 @@ pub type Svk = KzgSuccinctVerifyingKey; pub type BaseFieldEccChip<'chip> = halo2_ecc::ecc::BaseFieldEccChip<'chip, G1Affine>; pub type Halo2Loader<'chip> = loader::halo2::Halo2Loader>; +#[derive(Clone, Debug)] +pub struct PreprocessedAndDomainAsWitness { + // this is basically the vkey + pub preprocessed: Vec>, + pub k: AssignedValue, +} + +#[derive(Clone, Debug)] pub struct SnarkAggregationWitness<'a> { pub previous_instances: Vec>>, pub accumulator: KzgAccumulator>>, /// This returns the assigned `preprocessed` and `transcript_initial_state` values as a vector of assigned values, one for each aggregated snark. /// These can then be exposed as public instances. - /// - /// This is only useful if preprocessed digest is loaded as witness (i.e., `preprocessed_as_witness` is true in `aggregate`), so we set it to `None` otherwise. - pub preprocessed_digests: Option>>>, + pub preprocessed: Vec, } /// Different possible stages of universality the aggregation circuit can support @@ -60,7 +66,7 @@ pub enum VerifierUniversality { None, /// Preprocessed digest (commitments to fixed columns) is loaded as witness PreprocessedAsWitness, - /// Preprocessed as witness and number of rows in the circuit `n` loaded as witness + /// Preprocessed as witness and log_2(number of rows in the circuit) = k loaded as witness Full, } @@ -69,7 +75,7 @@ impl VerifierUniversality { self != &VerifierUniversality::None } - pub fn n_as_witness(&self) -> bool { + pub fn k_as_witness(&self) -> bool { self == &VerifierUniversality::Full } } @@ -117,7 +123,7 @@ where }; let mut previous_instances = Vec::with_capacity(snarks.len()); - let mut preprocessed_digests = Vec::with_capacity(snarks.len()); + let mut preprocessed_witnesses = Vec::with_capacity(snarks.len()); // to avoid re-loading the spec each time, we create one transcript and clear the stream let mut transcript = PoseidonTranscript::>, &[u8]>::from_spec( loader, @@ -131,11 +137,11 @@ where .flat_map(|snark: &Snark| { let protocol = if preprocessed_as_witness { // always load `domain.n` as witness if vkey is witness - snark.protocol.loaded_preprocessed_as_witness(loader, universality.n_as_witness()) + snark.protocol.loaded_preprocessed_as_witness(loader, universality.k_as_witness()) } else { snark.protocol.loaded(loader) }; - let inputs = protocol + let preprocessed = protocol .preprocessed .iter() .flat_map(|preprocessed| { @@ -148,19 +154,18 @@ where .chain( protocol.transcript_initial_state.clone().map(|scalar| scalar.into_assigned()), ) - .chain( - protocol - .domain_as_witness - .as_ref() - .map(|domain| domain.n.clone().into_assigned()), - ) // If `n` is witness, add it as part of input - .chain( - protocol - .domain_as_witness - .as_ref() - .map(|domain| domain.gen.clone().into_assigned()), - ) // If `n` is witness, add the generator of the order `n` subgroup as part of input .collect_vec(); + // Store `k` as witness. If `k` was fixed, assign it as a constant. + let k = protocol + .domain_as_witness + .as_ref() + .map(|domain| domain.k.clone().into_assigned()) + .unwrap_or_else(|| { + loader.ctx_mut().main().load_constant(Fr::from(protocol.domain.k as u64)) + }); + let preprocessed_and_k = PreprocessedAndDomainAsWitness { preprocessed, k }; + preprocessed_witnesses.push(preprocessed_and_k); + let instances = assign_instances(&snark.instances); // read the transcript and perform Fiat-Shamir @@ -179,7 +184,6 @@ where previous_instances.push( instances.into_iter().flatten().map(|scalar| scalar.into_assigned()).collect(), ); - preprocessed_digests.push(inputs); accumulator }) @@ -198,9 +202,12 @@ where } else { accumulators.pop().unwrap() }; - let preprocessed_digests = preprocessed_as_witness.then_some(preprocessed_digests); - SnarkAggregationWitness { previous_instances, accumulator, preprocessed_digests } + SnarkAggregationWitness { + previous_instances, + accumulator, + preprocessed: preprocessed_witnesses, + } } /// Same as `FlexGateConfigParams` except we assume a single Phase and default 'Vertical' strategy. @@ -278,10 +285,8 @@ pub struct AggregationCircuit { previous_instances: Vec>>, /// This returns the assigned `preprocessed_digest` (vkey), optional `transcript_initial_state`, `domain.n` (optional), and `omega` (optional) values as a vector of assigned values, one for each aggregated snark. /// These can then be exposed as public instances. - /// - /// This is only useful if preprocessed digest is loaded as witness (i.e., `universality != None`), so we set it to `None` if `universality == None`. #[getset(get = "pub")] - preprocessed_digests: Option>>>, + preprocessed: Vec, // accumulation scheme proof, no longer used // pub as_proof: Vec, } @@ -380,7 +385,7 @@ impl AggregationCircuit { let loader = Halo2Loader::new(ecc_chip, pool); // run witness and copy constraint generation - let SnarkAggregationWitness { previous_instances, accumulator, preprocessed_digests } = + let SnarkAggregationWitness { previous_instances, accumulator, preprocessed } = aggregate::(&svk, &loader, &snarks, as_proof.as_slice(), universality); let lhs = accumulator.lhs.assigned(); let rhs = accumulator.rhs.assigned(); @@ -412,7 +417,7 @@ impl AggregationCircuit { ); // expose accumulator as public instances builder.assigned_instances[0] = accumulator; - Self { builder, previous_instances, preprocessed_digests } + Self { builder, previous_instances, preprocessed } } /// Re-expose the previous public instances of aggregated snarks again. diff --git a/snark-verifier/src/verifier/plonk/protocol.rs b/snark-verifier/src/verifier/plonk/protocol.rs index 098e7de9..9260e572 100644 --- a/snark-verifier/src/verifier/plonk/protocol.rs +++ b/snark-verifier/src/verifier/plonk/protocol.rs @@ -23,7 +23,9 @@ where C: CurveAffine, L: Loader, { - /// Number of rows in the domain + /// 2k is the number of rows in the domain + pub k: L::LoadedScalar, + /// n = 2k is the number of rows in the domain pub n: L::LoadedScalar, /// Generator of the domain pub gen: L::LoadedScalar, @@ -65,7 +67,6 @@ where serialize = "L::LoadedScalar: Serialize", deserialize = "L::LoadedScalar: Deserialize<'de>" ))] - #[serde(skip_serializing_if = "Option::is_none")] /// Optional: load `domain.n` and `domain.gen` as a witness pub domain_as_witness: Option>, @@ -176,14 +177,15 @@ mod halo2 { use crate::{ loader::{ halo2::{EccInstructions, Halo2Loader}, - LoadedScalar, + LoadedScalar, ScalarLoader, }, util::arithmetic::CurveAffine, verifier::plonk::PlonkProtocol, }; + use halo2_base::utils::bit_length; use std::rc::Rc; - use super::DomainAsWitness; + use super::{DomainAsWitness, PrimeField}; impl PlonkProtocol where @@ -195,13 +197,21 @@ mod halo2 { pub fn loaded_preprocessed_as_witness>( &self, loader: &Rc>, - load_n_as_witness: bool, + load_k_as_witness: bool, ) -> PlonkProtocol>> { - let domain_as_witness = load_n_as_witness.then(|| { - let n = loader.assign_scalar(C::Scalar::from(self.domain.n as u64)); - let gen = loader.assign_scalar(self.domain.gen); + let domain_as_witness = load_k_as_witness.then(|| { + let k = loader.assign_scalar(C::Scalar::from(self.domain.k as u64)); + // n = 2^k + let two = loader.load_const(&C::Scalar::from(2)); + let n = two.pow_var(&k, bit_length(C::Scalar::S as u64) + 1); + // gen = omega = ROOT_OF_UNITY ^ {2^{S - k}}, where ROOT_OF_UNITY is primitive 2^S root of unity + // this makes omega a 2^k root of unity + let root_of_unity = loader.load_const(&C::Scalar::ROOT_OF_UNITY); + let s = loader.load_const(&C::Scalar::from(C::Scalar::S as u64)); + let exp = two.pow_var(&(s - &k), bit_length(C::Scalar::S as u64)); // if S - k < 0, constraint on max bits will fail + let gen = root_of_unity.pow_var(&exp, C::Scalar::S as usize); // 2^{S - k} < 2^S for k > 0 let gen_inv = gen.invert().expect("subgroup generation is invertible"); - DomainAsWitness { n, gen, gen_inv } + DomainAsWitness { k, n, gen, gen_inv } }); let preprocessed = self From 260962d4b597b4d470d074092c7c9e3b6fb0c378 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Fri, 8 Sep 2023 07:47:45 -0700 Subject: [PATCH 12/19] Move `OptimizedPoseidonSpec` to `halo2-base` (#31) * chore: move `OptimizedPoseidonSpec` to `halo2-base` * Bump version to 0.1.5 and remove poseidon-rs dep --- snark-verifier-sdk/Cargo.toml | 24 +- snark-verifier-sdk/src/halo2.rs | 2 +- snark-verifier/Cargo.toml | 6 +- snark-verifier/src/util/hash.rs | 4 +- snark-verifier/src/util/hash/poseidon.rs | 343 +----------------- .../src/util/hash/poseidon/tests.rs | 2 +- 6 files changed, 38 insertions(+), 343 deletions(-) diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index a62b3b0c..681f9121 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snark-verifier-sdk" -version = "0.1.4" +version = "0.1.5" edition = "2021" [dependencies] @@ -22,14 +22,14 @@ snark-verifier = { path = "../snark-verifier", default-features = false } getset = "0.1.2" # loader_evm -ethereum-types = { version = "0.14.1", default-features = false, features = ["std"], optional = true } -# sha3 = { version = "0.10", optional = true } -# revm = { version = "2.3.1", optional = true } -# bytes = { version = "1.2", optional = true } -# rlp = { version = "0.5", default-features = false, features = ["std"], optional = true } +ethereum-types = { version = "0.14.1", default-features = false, features = [ + "std", +], optional = true } # zkevm benchmarks -zkevm-circuits = { git = "https://github.com/privacy-scaling-explorations/zkevm-circuits.git", rev = "f834e61", features = ["test"], optional = true } +zkevm-circuits = { git = "https://github.com/privacy-scaling-explorations/zkevm-circuits.git", rev = "f834e61", features = [ + "test", +], optional = true } bus-mapping = { git = "https://github.com/privacy-scaling-explorations/zkevm-circuits.git", rev = "f834e61", optional = true } eth-types = { git = "https://github.com/privacy-scaling-explorations/zkevm-circuits.git", rev = "f834e61", optional = true } mock = { git = "https://github.com/privacy-scaling-explorations/zkevm-circuits.git", rev = "f834e61", optional = true } @@ -45,7 +45,13 @@ crossterm = { version = "0.25" } tui = { version = "0.19", default-features = false, features = ["crossterm"] } [features] -default = ["loader_halo2", "loader_evm", "halo2-axiom", "halo2-base/jemallocator", "display"] +default = [ + "loader_halo2", + "loader_evm", + "halo2-axiom", + "halo2-base/jemallocator", + "display", +] display = ["snark-verifier/display", "dep:ark-std"] loader_evm = ["snark-verifier/loader_evm", "dep:ethereum-types"] loader_halo2 = ["snark-verifier/loader_halo2"] @@ -74,4 +80,4 @@ harness = false [[bench]] name = "read_pk" required-features = ["loader_halo2"] -harness = false \ No newline at end of file +harness = false diff --git a/snark-verifier-sdk/src/halo2.rs b/snark-verifier-sdk/src/halo2.rs index 06d5e622..aa5f8810 100644 --- a/snark-verifier-sdk/src/halo2.rs +++ b/snark-verifier-sdk/src/halo2.rs @@ -2,6 +2,7 @@ use super::{read_instances, write_instances, CircuitExt, PlonkSuccinctVerifier, #[cfg(feature = "display")] use ark_std::{end_timer, start_timer}; use halo2_base::halo2_proofs; +pub use halo2_base::poseidon::hasher::spec::OptimizedPoseidonSpec; use halo2_proofs::{ circuit::Layouter, halo2curves::{ @@ -26,7 +27,6 @@ use halo2_proofs::{ use itertools::Itertools; use lazy_static::lazy_static; use rand::{rngs::StdRng, SeedableRng}; -pub use snark_verifier::util::hash::OptimizedPoseidonSpec; use snark_verifier::{ cost::CostEstimation, loader::native::NativeLoader, diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index fbc40c85..2fbe6682 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snark-verifier" -version = "0.1.4" +version = "0.1.5" edition = "2021" [dependencies] @@ -16,10 +16,6 @@ pairing = { version = "0.23" } # Use halo2-base as non-optional dependency because it re-exports halo2_proofs, halo2curves, and poseidon, using different repos based on feature flag "halo2-axiom" or "halo2-pse" halo2-base = { git = "https://github.com/axiom-crypto/halo2-lib.git", branch = "develop", default-features = false } -# This is Scroll's audited poseidon circuit. We only use it for the Native Poseidon spec. We do not use the halo2 circuit at all (and it wouldn't even work because the halo2_proofs tag is not compatbile). -# We forked it to upgrade to ff v0.13 and removed the circuit module -poseidon-rs = { git = "https://github.com/axiom-crypto/poseidon-circuit.git", rev = "1aee4a1" } -# poseidon-circuit = { git = "https://github.com/scroll-tech/poseidon-circuit.git", rev = "50015b7" } # parallel rayon = { version = "1.7", optional = true } diff --git a/snark-verifier/src/util/hash.rs b/snark-verifier/src/util/hash.rs index a8fe168c..dfc02cf0 100644 --- a/snark-verifier/src/util/hash.rs +++ b/snark-verifier/src/util/hash.rs @@ -4,7 +4,9 @@ mod poseidon; #[cfg(feature = "loader_halo2")] -pub use crate::util::hash::poseidon::{OptimizedPoseidonSpec, Poseidon}; +pub use crate::util::hash::poseidon::Poseidon; +#[cfg(feature = "loader_halo2")] +pub(crate) use halo2_base::poseidon::hasher::spec::OptimizedPoseidonSpec; #[cfg(feature = "loader_evm")] pub use sha3::{Digest, Keccak256}; diff --git a/snark-verifier/src/util/hash/poseidon.rs b/snark-verifier/src/util/hash/poseidon.rs index e826ac52..740f4c72 100644 --- a/snark-verifier/src/util/hash/poseidon.rs +++ b/snark-verifier/src/util/hash/poseidon.rs @@ -1,4 +1,7 @@ -#![allow(clippy::needless_range_loop)] // for clarity of matrix operations +//! Trait based implementation of Poseidon permutation + +use halo2_base::poseidon::hasher::{mds::SparseMDSMatrix, spec::OptimizedPoseidonSpec}; + use crate::{ loader::{LoadedScalar, ScalarLoader}, util::{ @@ -6,323 +9,11 @@ use crate::{ Itertools, }, }; -use poseidon_rs::poseidon::primitives::Spec as PoseidonSpec; // trait use std::{iter, marker::PhantomData, mem}; #[cfg(test)] mod tests; -// struct so we can use PoseidonSpec trait to generate round constants and MDS matrix -#[derive(Debug)] -pub struct Poseidon128Pow5Gen< - F: PrimeField, - const T: usize, - const RATE: usize, - const R_F: usize, - const R_P: usize, - const SECURE_MDS: usize, -> { - _marker: PhantomData, -} - -impl< - F: PrimeField, - const T: usize, - const RATE: usize, - const R_F: usize, - const R_P: usize, - const SECURE_MDS: usize, - > PoseidonSpec for Poseidon128Pow5Gen -{ - fn full_rounds() -> usize { - R_F - } - - fn partial_rounds() -> usize { - R_P - } - - fn sbox(val: F) -> F { - val.pow_vartime([5]) - } - - // see "Avoiding insecure matrices" in Section 2.3 of https://eprint.iacr.org/2019/458.pdf - // most Specs used in practice have SECURE_MDS = 0 - fn secure_mds() -> usize { - SECURE_MDS - } -} - -// We use the optimized Poseidon implementation described in Supplementary Material Section B of https://eprint.iacr.org/2019/458.pdf -// This involves some further computation of optimized constants and sparse MDS matrices beyond what the Scroll PoseidonSpec generates -// The implementation below is adapted from https://github.com/privacy-scaling-explorations/poseidon - -/// `OptimizedPoseidonSpec` holds construction parameters as well as constants that are used in -/// permutation step. -#[derive(Debug, Clone)] -pub struct OptimizedPoseidonSpec { - pub(crate) r_f: usize, - pub(crate) mds_matrices: MDSMatrices, - pub(crate) constants: OptimizedConstants, -} - -/// `OptimizedConstants` has round constants that are added each round. While -/// full rounds has T sized constants there is a single constant for each -/// partial round -#[derive(Debug, Clone)] -pub struct OptimizedConstants { - pub(crate) start: Vec<[F; T]>, - pub(crate) partial: Vec, - pub(crate) end: Vec<[F; T]>, -} - -/// The type used to hold the MDS matrix -pub(crate) type Mds = [[F; T]; T]; - -/// `MDSMatrices` holds the MDS matrix as well as transition matrix which is -/// also called `pre_sparse_mds` and sparse matrices that enables us to reduce -/// number of multiplications in apply MDS step -#[derive(Debug, Clone)] -pub struct MDSMatrices { - pub(crate) mds: MDSMatrix, - pub(crate) pre_sparse_mds: MDSMatrix, - pub(crate) sparse_matrices: Vec>, -} - -/// `SparseMDSMatrix` are in `[row], [hat | identity]` form and used in linear -/// layer of partial rounds instead of the original MDS -#[derive(Debug, Clone)] -pub struct SparseMDSMatrix { - pub(crate) row: [F; T], - pub(crate) col_hat: [F; RATE], -} - -/// `MDSMatrix` is applied to `State` to achive linear layer of Poseidon -#[derive(Clone, Debug)] -pub struct MDSMatrix(pub(crate) Mds); - -impl MDSMatrix { - pub(crate) fn mul_vector(&self, v: &[F; T]) -> [F; T] { - let mut res = [F::ZERO; T]; - for i in 0..T { - for j in 0..T { - res[i] += self.0[i][j] * v[j]; - } - } - res - } - - fn identity() -> Mds { - let mut mds = [[F::ZERO; T]; T]; - for i in 0..T { - mds[i][i] = F::ONE; - } - mds - } - - /// Multiplies two MDS matrices. Used in sparse matrix calculations - fn mul(&self, other: &Self) -> Self { - let mut res = [[F::ZERO; T]; T]; - for i in 0..T { - for j in 0..T { - for k in 0..T { - res[i][j] += self.0[i][k] * other.0[k][j]; - } - } - } - Self(res) - } - - fn transpose(&self) -> Self { - let mut res = [[F::ZERO; T]; T]; - for i in 0..T { - for j in 0..T { - res[i][j] = self.0[j][i]; - } - } - Self(res) - } - - fn determinant(m: [[F; N]; N]) -> F { - let mut res = F::ONE; - let mut m = m; - for i in 0..N { - let mut pivot = i; - while m[pivot][i] == F::ZERO { - pivot += 1; - assert!(pivot < N, "matrix is not invertible"); - } - if pivot != i { - res = -res; - m.swap(pivot, i); - } - res *= m[i][i]; - let inv = m[i][i].invert().unwrap(); - for j in i + 1..N { - let factor = m[j][i] * inv; - for k in i + 1..N { - m[j][k] -= m[i][k] * factor; - } - } - } - res - } - - /// See Section B in Supplementary Material https://eprint.iacr.org/2019/458.pdf - /// Factorises an MDS matrix `M` into `M'` and `M''` where `M = M' * M''`. - /// Resulted `M''` matrices are the sparse ones while `M'` will contribute - /// to the accumulator of the process - fn factorise(&self) -> (Self, SparseMDSMatrix) { - assert_eq!(RATE + 1, T); - // Given `(t-1 * t-1)` MDS matrix called `hat` constructs the `t * t` matrix in - // form `[[1 | 0], [0 | m]]`, ie `hat` is the right bottom sub-matrix - let prime = |hat: Mds| -> Self { - let mut prime = Self::identity(); - for (prime_row, hat_row) in prime.iter_mut().skip(1).zip(hat.iter()) { - for (el_prime, el_hat) in prime_row.iter_mut().skip(1).zip(hat_row.iter()) { - *el_prime = *el_hat; - } - } - Self(prime) - }; - - // Given `(t-1)` sized `w_hat` vector constructs the matrix in form - // `[[m_0_0 | m_0_i], [w_hat | identity]]` - let prime_prime = |w_hat: [F; RATE]| -> Mds { - let mut prime_prime = Self::identity(); - prime_prime[0] = self.0[0]; - for (row, w) in prime_prime.iter_mut().skip(1).zip(w_hat.iter()) { - row[0] = *w - } - prime_prime - }; - - let w = self.0.iter().skip(1).map(|row| row[0]).collect::>(); - // m_hat is the `(t-1 * t-1)` right bottom sub-matrix of m := self.0 - let mut m_hat = [[F::ZERO; RATE]; RATE]; - for i in 0..RATE { - for j in 0..RATE { - m_hat[i][j] = self.0[i + 1][j + 1]; - } - } - // w_hat = m_hat^{-1} * w, where m_hat^{-1} is matrix inverse and * is matrix mult - // we avoid computing m_hat^{-1} explicitly by using Cramer's rule: https://en.wikipedia.org/wiki/Cramer%27s_rule - let mut w_hat = [F::ZERO; RATE]; - let det = Self::determinant(m_hat); - let det_inv = Option::::from(det.invert()).expect("matrix is not invertible"); - for j in 0..RATE { - let mut m_hat_j = m_hat; - for i in 0..RATE { - m_hat_j[i][j] = w[i]; - } - w_hat[j] = Self::determinant(m_hat_j) * det_inv; - } - let m_prime = prime(m_hat); - let m_prime_prime = prime_prime(w_hat); - // row = first row of m_prime_prime.transpose() = first column of m_prime_prime - let row: [F; T] = - m_prime_prime.iter().map(|row| row[0]).collect::>().try_into().unwrap(); - // col_hat = first column of m_prime_prime.transpose() without first element = first row of m_prime_prime without first element - let col_hat: [F; RATE] = m_prime_prime[0][1..].try_into().unwrap(); - (m_prime, SparseMDSMatrix { row, col_hat }) - } -} - -impl OptimizedPoseidonSpec { - /// Generate new spec with specific number of full and partial rounds. `SECURE_MDS` is usually 0, but may need to be specified because insecure matrices may sometimes be generated - pub fn new() -> Self - where - F: FieldExt, - { - let (round_constants, mds, mds_inv) = - Poseidon128Pow5Gen::::constants(); - let mds = MDSMatrix(mds); - let inverse_mds = MDSMatrix(mds_inv); - - let constants = - Self::calculate_optimized_constants(R_F, R_P, round_constants, &inverse_mds); - let (sparse_matrices, pre_sparse_mds) = Self::calculate_sparse_matrices(R_P, &mds); - - Self { - r_f: R_F, - constants, - mds_matrices: MDSMatrices { mds, sparse_matrices, pre_sparse_mds }, - } - } - - fn calculate_optimized_constants( - r_f: usize, - r_p: usize, - constants: Vec<[F; T]>, - inverse_mds: &MDSMatrix, - ) -> OptimizedConstants { - let (number_of_rounds, r_f_half) = (r_f + r_p, r_f / 2); - assert_eq!(constants.len(), number_of_rounds); - - // Calculate optimized constants for first half of the full rounds - let mut constants_start: Vec<[F; T]> = vec![[F::ZERO; T]; r_f_half]; - constants_start[0] = constants[0]; - for (optimized, constants) in - constants_start.iter_mut().skip(1).zip(constants.iter().skip(1)) - { - *optimized = inverse_mds.mul_vector(constants); - } - - // Calculate constants for partial rounds - let mut acc = constants[r_f_half + r_p]; - let mut constants_partial = vec![F::ZERO; r_p]; - for (optimized, constants) in constants_partial - .iter_mut() - .rev() - .zip(constants.iter().skip(r_f_half).rev().skip(r_f_half)) - { - let mut tmp = inverse_mds.mul_vector(&acc); - *optimized = tmp[0]; - - tmp[0] = F::ZERO; - for ((acc, tmp), constant) in acc.iter_mut().zip(tmp).zip(constants.iter()) { - *acc = tmp + constant - } - } - constants_start.push(inverse_mds.mul_vector(&acc)); - - // Calculate optimized constants for ending half of the full rounds - let mut constants_end: Vec<[F; T]> = vec![[F::ZERO; T]; r_f_half - 1]; - for (optimized, constants) in - constants_end.iter_mut().zip(constants.iter().skip(r_f_half + r_p + 1)) - { - *optimized = inverse_mds.mul_vector(constants); - } - - OptimizedConstants { - start: constants_start, - partial: constants_partial, - end: constants_end, - } - } - - fn calculate_sparse_matrices( - r_p: usize, - mds: &MDSMatrix, - ) -> (Vec>, MDSMatrix) { - let mds = mds.transpose(); - let mut acc = mds.clone(); - let mut sparse_matrices = (0..r_p) - .map(|_| { - let (m_prime, m_prime_prime) = acc.factorise(); - acc = mds.mul(&m_prime); - m_prime_prime - }) - .collect::>>(); - - sparse_matrices.reverse(); - (sparse_matrices, acc.transpose()) - } -} - -// ================ END OF CONSTRUCTION OF POSEIDON SPEC ==================== - -// now we get to actual trait based implementation of Poseidon permutation // this works for any loader, where the two loaders used are NativeLoader (native rust) and Halo2Loader (ZK circuit) #[derive(Clone, Debug)] struct State { @@ -403,9 +94,9 @@ impl, const T: usize, const RATE: usize> State fn apply_sparse_mds(&mut self, mds: &SparseMDSMatrix) { self.inner = iter::once( self.loader() - .sum_with_coeff(&mds.row.iter().cloned().zip(self.inner.iter()).collect_vec()), + .sum_with_coeff(&mds.row().iter().cloned().zip(self.inner.iter()).collect_vec()), ) - .chain(mds.col_hat.iter().zip(self.inner.iter().skip(1)).map(|(coeff, state)| { + .chain(mds.col_hat().iter().zip(self.inner.iter().skip(1)).map(|(coeff, state)| { self.loader().sum_with_coeff(&[(*coeff, &self.inner[0]), (F::ONE, state)]) })) .collect_vec() @@ -475,35 +166,35 @@ impl, const T: usize, const RATE: usize> Posei } fn permutation(&mut self, inputs: &[L]) { - let r_f = self.spec.r_f / 2; - let mds = self.spec.mds_matrices.mds.0; - let pre_sparse_mds = self.spec.mds_matrices.pre_sparse_mds.0; - let sparse_matrices = &self.spec.mds_matrices.sparse_matrices; + let r_f = self.spec.r_f() / 2; + let mds = self.spec.mds_matrices().mds().as_ref(); + let pre_sparse_mds = self.spec.mds_matrices().pre_sparse_mds().as_ref(); + let sparse_matrices = &self.spec.mds_matrices().sparse_matrices(); // First half of the full rounds - let constants = &self.spec.constants.start; + let constants = self.spec.constants().start(); self.state.absorb_with_pre_constants(inputs, &constants[0]); for constants in constants.iter().skip(1).take(r_f - 1) { self.state.sbox_full(constants); - self.state.apply_mds(&mds); + self.state.apply_mds(mds); } self.state.sbox_full(constants.last().unwrap()); - self.state.apply_mds(&pre_sparse_mds); + self.state.apply_mds(pre_sparse_mds); // Partial rounds - let constants = &self.spec.constants.partial; + let constants = self.spec.constants().partial(); for (constant, sparse_mds) in constants.iter().zip(sparse_matrices.iter()) { self.state.sbox_part(constant); self.state.apply_sparse_mds(sparse_mds); } // Second half of the full rounds - let constants = &self.spec.constants.end; + let constants = self.spec.constants().end(); for constants in constants.iter() { self.state.sbox_full(constants); - self.state.apply_mds(&mds); + self.state.apply_mds(mds); } self.state.sbox_full(&[F::ZERO; T]); - self.state.apply_mds(&mds); + self.state.apply_mds(mds); } } diff --git a/snark-verifier/src/util/hash/poseidon/tests.rs b/snark-verifier/src/util/hash/poseidon/tests.rs index 76793c91..507b1d7c 100644 --- a/snark-verifier/src/util/hash/poseidon/tests.rs +++ b/snark-verifier/src/util/hash/poseidon/tests.rs @@ -24,7 +24,7 @@ fn test_mds() { "11597556804922396090267472882856054602429588299176362916247939723151043581408", ], ]; - for (row1, row2) in mds.iter().zip_eq(spec.mds_matrices.mds.0.iter()) { + for (row1, row2) in mds.iter().zip_eq(spec.mds_matrices().mds().as_ref().iter()) { for (e1, e2) in row1.iter().zip_eq(row2.iter()) { assert_eq!(Fr::from_str_vartime(e1).unwrap(), *e2); } From 1f5ebd39307d8e1824856f9e683a35a59b145a8d Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Sun, 10 Sep 2023 14:39:33 -0700 Subject: [PATCH 13/19] chore: util::hash available without loader_halo2 feature --- snark-verifier-sdk/Cargo.toml | 4 ++-- snark-verifier/src/util/hash.rs | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index 681f9121..1d8019af 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -46,8 +46,8 @@ tui = { version = "0.19", default-features = false, features = ["crossterm"] } [features] default = [ - "loader_halo2", - "loader_evm", + #"loader_halo2", + #"loader_evm", "halo2-axiom", "halo2-base/jemallocator", "display", diff --git a/snark-verifier/src/util/hash.rs b/snark-verifier/src/util/hash.rs index dfc02cf0..245e9d24 100644 --- a/snark-verifier/src/util/hash.rs +++ b/snark-verifier/src/util/hash.rs @@ -1,11 +1,8 @@ //! Hash algorithms. -#[cfg(feature = "loader_halo2")] mod poseidon; -#[cfg(feature = "loader_halo2")] pub use crate::util::hash::poseidon::Poseidon; -#[cfg(feature = "loader_halo2")] pub(crate) use halo2_base::poseidon::hasher::spec::OptimizedPoseidonSpec; #[cfg(feature = "loader_evm")] From a0fa8ec6c27eb0884b9de88b61708f240e138064 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Sun, 10 Sep 2023 14:43:34 -0700 Subject: [PATCH 14/19] chore: nit --- snark-verifier-sdk/Cargo.toml | 4 ++-- snark-verifier/src/util/hash.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index 1d8019af..681f9121 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -46,8 +46,8 @@ tui = { version = "0.19", default-features = false, features = ["crossterm"] } [features] default = [ - #"loader_halo2", - #"loader_evm", + "loader_halo2", + "loader_evm", "halo2-axiom", "halo2-base/jemallocator", "display", diff --git a/snark-verifier/src/util/hash.rs b/snark-verifier/src/util/hash.rs index 245e9d24..a14eec23 100644 --- a/snark-verifier/src/util/hash.rs +++ b/snark-verifier/src/util/hash.rs @@ -3,6 +3,7 @@ mod poseidon; pub use crate::util::hash::poseidon::Poseidon; +#[cfg(feature = "loader_halo2")] pub(crate) use halo2_base::poseidon::hasher::spec::OptimizedPoseidonSpec; #[cfg(feature = "loader_evm")] From df944c27989bebe9b981f9a6f3ae7f64cb51e6d5 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Mon, 11 Sep 2023 00:33:26 -0700 Subject: [PATCH 15/19] [feat] change yul code into Solidity assembly (#32) feat: change yul code into Solidity assembly Just changes to wrapping yul in solidity assembly block --- .github/workflows/ci.yaml | 4 + snark-verifier-sdk/Cargo.toml | 6 +- .../examples/StandardPlonkVerifier.sol | 1437 +++++++++++++++++ snark-verifier-sdk/examples/standard_plonk.rs | 216 +++ snark-verifier-sdk/src/evm.rs | 8 +- snark-verifier/Cargo.toml | 2 +- .../examples/evm-verifier-with-accumulator.rs | 2 +- snark-verifier/examples/evm-verifier.rs | 2 +- snark-verifier/src/loader/evm.rs | 4 +- snark-verifier/src/loader/evm/code.rs | 66 +- snark-verifier/src/loader/evm/loader.rs | 18 +- snark-verifier/src/loader/evm/util.rs | 5 +- 12 files changed, 1714 insertions(+), 56 deletions(-) create mode 100644 snark-verifier-sdk/examples/StandardPlonkVerifier.sol create mode 100644 snark-verifier-sdk/examples/standard_plonk.rs diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7261444e..733bfc9c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -29,6 +29,10 @@ jobs: - name: Run test run: cargo test --all -- --nocapture + - name: Run example + working-directory: "snark-verifier-sdk" + run: cargo run --example standard_plonk + lint: name: Lint runs-on: ubuntu-latest diff --git a/snark-verifier-sdk/Cargo.toml b/snark-verifier-sdk/Cargo.toml index 681f9121..db1f7071 100644 --- a/snark-verifier-sdk/Cargo.toml +++ b/snark-verifier-sdk/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snark-verifier-sdk" -version = "0.1.5" +version = "0.1.6" edition = "2021" [dependencies] @@ -81,3 +81,7 @@ harness = false name = "read_pk" required-features = ["loader_halo2"] harness = false + +[[example]] +name = "standard_plonk" +required-features = ["loader_halo2", "loader_evm"] diff --git a/snark-verifier-sdk/examples/StandardPlonkVerifier.sol b/snark-verifier-sdk/examples/StandardPlonkVerifier.sol new file mode 100644 index 00000000..d6e9427c --- /dev/null +++ b/snark-verifier-sdk/examples/StandardPlonkVerifier.sol @@ -0,0 +1,1437 @@ + +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +contract Halo2Verifier { + fallback(bytes calldata) external returns (bytes memory) { + assembly { + let success := true + let f_p := 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47 + let f_q := 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001 + function validate_ec_point(x, y) -> valid { + { + let x_lt_p := lt(x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let y_lt_p := lt(y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + valid := and(x_lt_p, y_lt_p) + } + { + let y_square := mulmod(y, y, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_square := mulmod(x, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_cube := mulmod(x_square, x, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let x_cube_plus_3 := addmod(x_cube, 3, 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47) + let is_affine := eq(x_cube_plus_3, y_square) + valid := and(valid, is_affine) + } + } + mstore(0x20, mod(calldataload(0x0), f_q)) +mstore(0x40, mod(calldataload(0x20), f_q)) +mstore(0x60, mod(calldataload(0x40), f_q)) +mstore(0x80, mod(calldataload(0x60), f_q)) +mstore(0xa0, mod(calldataload(0x80), f_q)) +mstore(0xc0, mod(calldataload(0xa0), f_q)) +mstore(0xe0, mod(calldataload(0xc0), f_q)) +mstore(0x100, mod(calldataload(0xe0), f_q)) +mstore(0x120, mod(calldataload(0x100), f_q)) +mstore(0x140, mod(calldataload(0x120), f_q)) +mstore(0x160, mod(calldataload(0x140), f_q)) +mstore(0x180, mod(calldataload(0x160), f_q)) +mstore(0x0, 17740244582459666476042487670110999380715355991411842331101569887719361442506) + + { + let x := calldataload(0x180) + mstore(0x1a0, x) + let y := calldataload(0x1a0) + mstore(0x1c0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x1c0) + mstore(0x1e0, x) + let y := calldataload(0x1e0) + mstore(0x200, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x200) + mstore(0x220, x) + let y := calldataload(0x220) + mstore(0x240, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x260, keccak256(0x0, 608)) +{ + let hash := mload(0x260) + mstore(0x280, mod(hash, f_q)) + mstore(0x2a0, hash) + } + + { + let x := calldataload(0x240) + mstore(0x2c0, x) + let y := calldataload(0x260) + mstore(0x2e0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x280) + mstore(0x300, x) + let y := calldataload(0x2a0) + mstore(0x320, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x340, keccak256(0x2a0, 160)) +{ + let hash := mload(0x340) + mstore(0x360, mod(hash, f_q)) + mstore(0x380, hash) + } +mstore8(928, 1) +mstore(0x3a0, keccak256(0x380, 33)) +{ + let hash := mload(0x3a0) + mstore(0x3c0, mod(hash, f_q)) + mstore(0x3e0, hash) + } + + { + let x := calldataload(0x2c0) + mstore(0x400, x) + let y := calldataload(0x2e0) + mstore(0x420, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x300) + mstore(0x440, x) + let y := calldataload(0x320) + mstore(0x460, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x340) + mstore(0x480, x) + let y := calldataload(0x360) + mstore(0x4a0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x380) + mstore(0x4c0, x) + let y := calldataload(0x3a0) + mstore(0x4e0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x3c0) + mstore(0x500, x) + let y := calldataload(0x3e0) + mstore(0x520, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x540, keccak256(0x3e0, 352)) +{ + let hash := mload(0x540) + mstore(0x560, mod(hash, f_q)) + mstore(0x580, hash) + } + + { + let x := calldataload(0x400) + mstore(0x5a0, x) + let y := calldataload(0x420) + mstore(0x5c0, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x440) + mstore(0x5e0, x) + let y := calldataload(0x460) + mstore(0x600, y) + success := and(validate_ec_point(x, y), success) + } + + { + let x := calldataload(0x480) + mstore(0x620, x) + let y := calldataload(0x4a0) + mstore(0x640, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0x660, keccak256(0x580, 224)) +{ + let hash := mload(0x660) + mstore(0x680, mod(hash, f_q)) + mstore(0x6a0, hash) + } +mstore(0x6c0, mod(calldataload(0x4c0), f_q)) +mstore(0x6e0, mod(calldataload(0x4e0), f_q)) +mstore(0x700, mod(calldataload(0x500), f_q)) +mstore(0x720, mod(calldataload(0x520), f_q)) +mstore(0x740, mod(calldataload(0x540), f_q)) +mstore(0x760, mod(calldataload(0x560), f_q)) +mstore(0x780, mod(calldataload(0x580), f_q)) +mstore(0x7a0, mod(calldataload(0x5a0), f_q)) +mstore(0x7c0, mod(calldataload(0x5c0), f_q)) +mstore(0x7e0, mod(calldataload(0x5e0), f_q)) +mstore(0x800, mod(calldataload(0x600), f_q)) +mstore(0x820, mod(calldataload(0x620), f_q)) +mstore(0x840, mod(calldataload(0x640), f_q)) +mstore(0x860, mod(calldataload(0x660), f_q)) +mstore(0x880, mod(calldataload(0x680), f_q)) +mstore(0x8a0, mod(calldataload(0x6a0), f_q)) +mstore(0x8c0, mod(calldataload(0x6c0), f_q)) +mstore(0x8e0, mod(calldataload(0x6e0), f_q)) +mstore(0x900, mod(calldataload(0x700), f_q)) +mstore(0x920, mod(calldataload(0x720), f_q)) +mstore(0x940, mod(calldataload(0x740), f_q)) +mstore(0x960, mod(calldataload(0x760), f_q)) +mstore(0x980, mod(calldataload(0x780), f_q)) +mstore(0x9a0, mod(calldataload(0x7a0), f_q)) +mstore(0x9c0, mod(calldataload(0x7c0), f_q)) +mstore(0x9e0, mod(calldataload(0x7e0), f_q)) +mstore(0xa00, mod(calldataload(0x800), f_q)) +mstore(0xa20, mod(calldataload(0x820), f_q)) +mstore(0xa40, mod(calldataload(0x840), f_q)) +mstore(0xa60, mod(calldataload(0x860), f_q)) +mstore(0xa80, mod(calldataload(0x880), f_q)) +mstore(0xaa0, mod(calldataload(0x8a0), f_q)) +mstore(0xac0, keccak256(0x6a0, 1056)) +{ + let hash := mload(0xac0) + mstore(0xae0, mod(hash, f_q)) + mstore(0xb00, hash) + } +mstore8(2848, 1) +mstore(0xb20, keccak256(0xb00, 33)) +{ + let hash := mload(0xb20) + mstore(0xb40, mod(hash, f_q)) + mstore(0xb60, hash) + } + + { + let x := calldataload(0x8c0) + mstore(0xb80, x) + let y := calldataload(0x8e0) + mstore(0xba0, y) + success := and(validate_ec_point(x, y), success) + } +mstore(0xbc0, keccak256(0xb60, 96)) +{ + let hash := mload(0xbc0) + mstore(0xbe0, mod(hash, f_q)) + mstore(0xc00, hash) + } + + { + let x := calldataload(0x900) + mstore(0xc20, x) + let y := calldataload(0x920) + mstore(0xc40, y) + success := and(validate_ec_point(x, y), success) + } +{ + let x := mload(0x20) +x := add(x, shl(88, mload(0x40))) +x := add(x, shl(176, mload(0x60))) +mstore(3168, x) +let y := mload(0x80) +y := add(y, shl(88, mload(0xa0))) +y := add(y, shl(176, mload(0xc0))) +mstore(3200, y) + + success := and(validate_ec_point(x, y), success) + } +{ + let x := mload(0xe0) +x := add(x, shl(88, mload(0x100))) +x := add(x, shl(176, mload(0x120))) +mstore(3232, x) +let y := mload(0x140) +y := add(y, shl(88, mload(0x160))) +y := add(y, shl(176, mload(0x180))) +mstore(3264, y) + + success := and(validate_ec_point(x, y), success) + } +mstore(0xce0, mulmod(mload(0x680), mload(0x680), f_q)) +mstore(0xd00, mulmod(mload(0xce0), mload(0xce0), f_q)) +mstore(0xd20, mulmod(mload(0xd00), mload(0xd00), f_q)) +mstore(0xd40, mulmod(mload(0xd20), mload(0xd20), f_q)) +mstore(0xd60, mulmod(mload(0xd40), mload(0xd40), f_q)) +mstore(0xd80, mulmod(mload(0xd60), mload(0xd60), f_q)) +mstore(0xda0, mulmod(mload(0xd80), mload(0xd80), f_q)) +mstore(0xdc0, mulmod(mload(0xda0), mload(0xda0), f_q)) +mstore(0xde0, mulmod(mload(0xdc0), mload(0xdc0), f_q)) +mstore(0xe00, mulmod(mload(0xde0), mload(0xde0), f_q)) +mstore(0xe20, mulmod(mload(0xe00), mload(0xe00), f_q)) +mstore(0xe40, mulmod(mload(0xe20), mload(0xe20), f_q)) +mstore(0xe60, mulmod(mload(0xe40), mload(0xe40), f_q)) +mstore(0xe80, mulmod(mload(0xe60), mload(0xe60), f_q)) +mstore(0xea0, mulmod(mload(0xe80), mload(0xe80), f_q)) +mstore(0xec0, mulmod(mload(0xea0), mload(0xea0), f_q)) +mstore(0xee0, mulmod(mload(0xec0), mload(0xec0), f_q)) +mstore(0xf00, mulmod(mload(0xee0), mload(0xee0), f_q)) +mstore(0xf20, mulmod(mload(0xf00), mload(0xf00), f_q)) +mstore(0xf40, mulmod(mload(0xf20), mload(0xf20), f_q)) +mstore(0xf60, mulmod(mload(0xf40), mload(0xf40), f_q)) +mstore(0xf80, addmod(mload(0xf60), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) +mstore(0xfa0, mulmod(mload(0xf80), 21888232434711746154598842647110004286396165347431605739555851272621938401409, f_q)) +mstore(0xfc0, mulmod(mload(0xfa0), 20975929243409798062839949658616274858986091382510192949221301676705706354487, f_q)) +mstore(0xfe0, addmod(mload(0x680), 912313628429477159406456086641000229562273017905841394476902509870102141130, f_q)) +mstore(0x1000, mulmod(mload(0xfa0), 495188420091111145957709789221178673495499187437761988132837836548330853701, f_q)) +mstore(0x1020, addmod(mload(0x680), 21393054451748164076288695956036096415052865212978272355565366350027477641916, f_q)) +mstore(0x1040, mulmod(mload(0xfa0), 16064522944768515290584536219762686197737451920702130080538975732575755569557, f_q)) +mstore(0x1060, addmod(mload(0x680), 5823719927070759931661869525494588890810912479713904263159228454000052926060, f_q)) +mstore(0x1080, mulmod(mload(0xfa0), 14686510910986211321976396297238126901237973400949744736326777596334651355305, f_q)) +mstore(0x10a0, addmod(mload(0x680), 7201731960853063900270009448019148187310390999466289607371426590241157140312, f_q)) +mstore(0x10c0, mulmod(mload(0xfa0), 10939663269433627367777756708678102241564365262857670666700619874077960926249, f_q)) +mstore(0x10e0, addmod(mload(0x680), 10948579602405647854468649036579172846983999137558363676997584312497847569368, f_q)) +mstore(0x1100, mulmod(mload(0xfa0), 15402826414547299628414612080036060696555554914079673875872749760617770134879, f_q)) +mstore(0x1120, addmod(mload(0x680), 6485416457291975593831793665221214391992809486336360467825454425958038360738, f_q)) +mstore(0x1140, mulmod(mload(0xfa0), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q)) +mstore(0x1160, addmod(mload(0x680), 19102728315457599142069468034376470979900453007937332237837518576196438670601, f_q)) +mstore(0x1180, mulmod(mload(0xfa0), 1, f_q)) +mstore(0x11a0, addmod(mload(0x680), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q)) +mstore(0x11c0, mulmod(mload(0xfa0), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +mstore(0x11e0, addmod(mload(0x680), 20461838439117790833741043996939313553025008529160428886800406442142042007110, f_q)) +mstore(0x1200, mulmod(mload(0xfa0), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q)) +mstore(0x1220, addmod(mload(0x680), 2855281034601326619502779289517034852317245347382893578658160672914005347465, f_q)) +mstore(0x1240, mulmod(mload(0xfa0), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q)) +mstore(0x1260, addmod(mload(0x680), 18122161250104879439014068220095202351720788102473020950742332016437772306424, f_q)) +mstore(0x1280, mulmod(mload(0xfa0), 5854133144571823792863860130267644613802765696134002830362054821530146160770, f_q)) +mstore(0x12a0, addmod(mload(0x680), 16034109727267451429382545614989630474745598704282031513336149365045662334847, f_q)) +mstore(0x12c0, mulmod(mload(0xfa0), 14557038802599140430182096396825290815503940951075961210638273254419942783582, f_q)) +mstore(0x12e0, addmod(mload(0x680), 7331204069240134792064309348431984273044423449340073133059930932155865712035, f_q)) +mstore(0x1300, mulmod(mload(0xfa0), 9697063347556872083384215826199993067635178715531258559890418744774301211662, f_q)) +mstore(0x1320, addmod(mload(0x680), 12191179524282403138862189919057282020913185684884775783807785441801507283955, f_q)) +mstore(0x1340, mulmod(mload(0xfa0), 12459868075641381822485233712013080087763946065665469821362892189399541605692, f_q)) +mstore(0x1360, addmod(mload(0x680), 9428374796197893399761172033244195000784418334750564522335311997176266889925, f_q)) +mstore(0x1380, mulmod(mload(0xfa0), 6955697244493336113861667751840378876927906302623587437721024018233754910398, f_q)) +mstore(0x13a0, addmod(mload(0x680), 14932545627345939108384737993416896211620458097792446905977180168342053585219, f_q)) +mstore(0x13c0, mulmod(mload(0xfa0), 20345677989844117909528750049476969581182118546166966482506114734614108237981, f_q)) +mstore(0x13e0, addmod(mload(0x680), 1542564881995157312717655695780305507366245854249067861192089451961700257636, f_q)) +mstore(0x1400, mulmod(mload(0xfa0), 5289443209903185443361862148540090689648485914368835830972895623576469023722, f_q)) +mstore(0x1420, addmod(mload(0x680), 16598799661936089778884543596717184398899878486047198512725308562999339471895, f_q)) +mstore(0x1440, mulmod(mload(0xfa0), 557567375339945239933617516585967620814823575807691402619711360028043331811, f_q)) +mstore(0x1460, addmod(mload(0x680), 21330675496499329982312788228671307467733540824608342941078492826547765163806, f_q)) +{ + let prod := mload(0xfe0) + + prod := mulmod(mload(0x1020), prod, f_q) + mstore(0x1480, prod) + + prod := mulmod(mload(0x1060), prod, f_q) + mstore(0x14a0, prod) + + prod := mulmod(mload(0x10a0), prod, f_q) + mstore(0x14c0, prod) + + prod := mulmod(mload(0x10e0), prod, f_q) + mstore(0x14e0, prod) + + prod := mulmod(mload(0x1120), prod, f_q) + mstore(0x1500, prod) + + prod := mulmod(mload(0x1160), prod, f_q) + mstore(0x1520, prod) + + prod := mulmod(mload(0x11a0), prod, f_q) + mstore(0x1540, prod) + + prod := mulmod(mload(0x11e0), prod, f_q) + mstore(0x1560, prod) + + prod := mulmod(mload(0x1220), prod, f_q) + mstore(0x1580, prod) + + prod := mulmod(mload(0x1260), prod, f_q) + mstore(0x15a0, prod) + + prod := mulmod(mload(0x12a0), prod, f_q) + mstore(0x15c0, prod) + + prod := mulmod(mload(0x12e0), prod, f_q) + mstore(0x15e0, prod) + + prod := mulmod(mload(0x1320), prod, f_q) + mstore(0x1600, prod) + + prod := mulmod(mload(0x1360), prod, f_q) + mstore(0x1620, prod) + + prod := mulmod(mload(0x13a0), prod, f_q) + mstore(0x1640, prod) + + prod := mulmod(mload(0x13e0), prod, f_q) + mstore(0x1660, prod) + + prod := mulmod(mload(0x1420), prod, f_q) + mstore(0x1680, prod) + + prod := mulmod(mload(0x1460), prod, f_q) + mstore(0x16a0, prod) + + prod := mulmod(mload(0xf80), prod, f_q) + mstore(0x16c0, prod) + + } +mstore(0x1700, 32) +mstore(0x1720, 32) +mstore(0x1740, 32) +mstore(0x1760, mload(0x16c0)) +mstore(0x1780, 21888242871839275222246405745257275088548364400416034343698204186575808495615) +mstore(0x17a0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) +success := and(eq(staticcall(gas(), 0x5, 0x1700, 0xc0, 0x16e0, 0x20), 1), success) +{ + + let inv := mload(0x16e0) + let v + + v := mload(0xf80) + mstore(3968, mulmod(mload(0x16a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1460) + mstore(5216, mulmod(mload(0x1680), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1420) + mstore(5152, mulmod(mload(0x1660), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13e0) + mstore(5088, mulmod(mload(0x1640), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x13a0) + mstore(5024, mulmod(mload(0x1620), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1360) + mstore(4960, mulmod(mload(0x1600), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1320) + mstore(4896, mulmod(mload(0x15e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12e0) + mstore(4832, mulmod(mload(0x15c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x12a0) + mstore(4768, mulmod(mload(0x15a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1260) + mstore(4704, mulmod(mload(0x1580), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1220) + mstore(4640, mulmod(mload(0x1560), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x11e0) + mstore(4576, mulmod(mload(0x1540), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x11a0) + mstore(4512, mulmod(mload(0x1520), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1160) + mstore(4448, mulmod(mload(0x1500), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1120) + mstore(4384, mulmod(mload(0x14e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x10e0) + mstore(4320, mulmod(mload(0x14c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x10a0) + mstore(4256, mulmod(mload(0x14a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1060) + mstore(4192, mulmod(mload(0x1480), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x1020) + mstore(4128, mulmod(mload(0xfe0), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0xfe0, inv) + + } +mstore(0x17c0, mulmod(mload(0xfc0), mload(0xfe0), f_q)) +mstore(0x17e0, mulmod(mload(0x1000), mload(0x1020), f_q)) +mstore(0x1800, mulmod(mload(0x1040), mload(0x1060), f_q)) +mstore(0x1820, mulmod(mload(0x1080), mload(0x10a0), f_q)) +mstore(0x1840, mulmod(mload(0x10c0), mload(0x10e0), f_q)) +mstore(0x1860, mulmod(mload(0x1100), mload(0x1120), f_q)) +mstore(0x1880, mulmod(mload(0x1140), mload(0x1160), f_q)) +mstore(0x18a0, mulmod(mload(0x1180), mload(0x11a0), f_q)) +mstore(0x18c0, mulmod(mload(0x11c0), mload(0x11e0), f_q)) +mstore(0x18e0, mulmod(mload(0x1200), mload(0x1220), f_q)) +mstore(0x1900, mulmod(mload(0x1240), mload(0x1260), f_q)) +mstore(0x1920, mulmod(mload(0x1280), mload(0x12a0), f_q)) +mstore(0x1940, mulmod(mload(0x12c0), mload(0x12e0), f_q)) +mstore(0x1960, mulmod(mload(0x1300), mload(0x1320), f_q)) +mstore(0x1980, mulmod(mload(0x1340), mload(0x1360), f_q)) +mstore(0x19a0, mulmod(mload(0x1380), mload(0x13a0), f_q)) +mstore(0x19c0, mulmod(mload(0x13c0), mload(0x13e0), f_q)) +mstore(0x19e0, mulmod(mload(0x1400), mload(0x1420), f_q)) +mstore(0x1a00, mulmod(mload(0x1440), mload(0x1460), f_q)) +{ + let result := mulmod(mload(0x18a0), mload(0x20), f_q) +result := addmod(mulmod(mload(0x18c0), mload(0x40), f_q), result, f_q) +result := addmod(mulmod(mload(0x18e0), mload(0x60), f_q), result, f_q) +result := addmod(mulmod(mload(0x1900), mload(0x80), f_q), result, f_q) +result := addmod(mulmod(mload(0x1920), mload(0xa0), f_q), result, f_q) +result := addmod(mulmod(mload(0x1940), mload(0xc0), f_q), result, f_q) +result := addmod(mulmod(mload(0x1960), mload(0xe0), f_q), result, f_q) +result := addmod(mulmod(mload(0x1980), mload(0x100), f_q), result, f_q) +result := addmod(mulmod(mload(0x19a0), mload(0x120), f_q), result, f_q) +result := addmod(mulmod(mload(0x19c0), mload(0x140), f_q), result, f_q) +result := addmod(mulmod(mload(0x19e0), mload(0x160), f_q), result, f_q) +result := addmod(mulmod(mload(0x1a00), mload(0x180), f_q), result, f_q) +mstore(6688, result) + } +mstore(0x1a40, mulmod(mload(0x700), mload(0x6e0), f_q)) +mstore(0x1a60, addmod(mload(0x6c0), mload(0x1a40), f_q)) +mstore(0x1a80, addmod(mload(0x1a60), sub(f_q, mload(0x720)), f_q)) +mstore(0x1aa0, mulmod(mload(0x1a80), mload(0x820), f_q)) +mstore(0x1ac0, mulmod(mload(0x560), mload(0x1aa0), f_q)) +mstore(0x1ae0, mulmod(mload(0x780), mload(0x760), f_q)) +mstore(0x1b00, addmod(mload(0x740), mload(0x1ae0), f_q)) +mstore(0x1b20, addmod(mload(0x1b00), sub(f_q, mload(0x7a0)), f_q)) +mstore(0x1b40, mulmod(mload(0x1b20), mload(0x840), f_q)) +mstore(0x1b60, addmod(mload(0x1ac0), mload(0x1b40), f_q)) +mstore(0x1b80, mulmod(mload(0x560), mload(0x1b60), f_q)) +mstore(0x1ba0, addmod(1, sub(f_q, mload(0x920)), f_q)) +mstore(0x1bc0, mulmod(mload(0x1ba0), mload(0x18a0), f_q)) +mstore(0x1be0, addmod(mload(0x1b80), mload(0x1bc0), f_q)) +mstore(0x1c00, mulmod(mload(0x560), mload(0x1be0), f_q)) +mstore(0x1c20, mulmod(mload(0x9e0), mload(0x9e0), f_q)) +mstore(0x1c40, addmod(mload(0x1c20), sub(f_q, mload(0x9e0)), f_q)) +mstore(0x1c60, mulmod(mload(0x1c40), mload(0x17c0), f_q)) +mstore(0x1c80, addmod(mload(0x1c00), mload(0x1c60), f_q)) +mstore(0x1ca0, mulmod(mload(0x560), mload(0x1c80), f_q)) +mstore(0x1cc0, addmod(mload(0x980), sub(f_q, mload(0x960)), f_q)) +mstore(0x1ce0, mulmod(mload(0x1cc0), mload(0x18a0), f_q)) +mstore(0x1d00, addmod(mload(0x1ca0), mload(0x1ce0), f_q)) +mstore(0x1d20, mulmod(mload(0x560), mload(0x1d00), f_q)) +mstore(0x1d40, addmod(mload(0x9e0), sub(f_q, mload(0x9c0)), f_q)) +mstore(0x1d60, mulmod(mload(0x1d40), mload(0x18a0), f_q)) +mstore(0x1d80, addmod(mload(0x1d20), mload(0x1d60), f_q)) +mstore(0x1da0, mulmod(mload(0x560), mload(0x1d80), f_q)) +mstore(0x1dc0, addmod(1, sub(f_q, mload(0x17c0)), f_q)) +mstore(0x1de0, addmod(mload(0x17e0), mload(0x1800), f_q)) +mstore(0x1e00, addmod(mload(0x1de0), mload(0x1820), f_q)) +mstore(0x1e20, addmod(mload(0x1e00), mload(0x1840), f_q)) +mstore(0x1e40, addmod(mload(0x1e20), mload(0x1860), f_q)) +mstore(0x1e60, addmod(mload(0x1e40), mload(0x1880), f_q)) +mstore(0x1e80, addmod(mload(0x1dc0), sub(f_q, mload(0x1e60)), f_q)) +mstore(0x1ea0, mulmod(mload(0x880), mload(0x360), f_q)) +mstore(0x1ec0, addmod(mload(0x7e0), mload(0x1ea0), f_q)) +mstore(0x1ee0, addmod(mload(0x1ec0), mload(0x3c0), f_q)) +mstore(0x1f00, mulmod(mload(0x8a0), mload(0x360), f_q)) +mstore(0x1f20, addmod(mload(0x6c0), mload(0x1f00), f_q)) +mstore(0x1f40, addmod(mload(0x1f20), mload(0x3c0), f_q)) +mstore(0x1f60, mulmod(mload(0x1f40), mload(0x1ee0), f_q)) +mstore(0x1f80, mulmod(mload(0x1f60), mload(0x940), f_q)) +mstore(0x1fa0, mulmod(1, mload(0x360), f_q)) +mstore(0x1fc0, mulmod(mload(0x680), mload(0x1fa0), f_q)) +mstore(0x1fe0, addmod(mload(0x7e0), mload(0x1fc0), f_q)) +mstore(0x2000, addmod(mload(0x1fe0), mload(0x3c0), f_q)) +mstore(0x2020, mulmod(4131629893567559867359510883348571134090853742863529169391034518566172092834, mload(0x360), f_q)) +mstore(0x2040, mulmod(mload(0x680), mload(0x2020), f_q)) +mstore(0x2060, addmod(mload(0x6c0), mload(0x2040), f_q)) +mstore(0x2080, addmod(mload(0x2060), mload(0x3c0), f_q)) +mstore(0x20a0, mulmod(mload(0x2080), mload(0x2000), f_q)) +mstore(0x20c0, mulmod(mload(0x20a0), mload(0x920), f_q)) +mstore(0x20e0, addmod(mload(0x1f80), sub(f_q, mload(0x20c0)), f_q)) +mstore(0x2100, mulmod(mload(0x20e0), mload(0x1e80), f_q)) +mstore(0x2120, addmod(mload(0x1da0), mload(0x2100), f_q)) +mstore(0x2140, mulmod(mload(0x560), mload(0x2120), f_q)) +mstore(0x2160, mulmod(mload(0x8c0), mload(0x360), f_q)) +mstore(0x2180, addmod(mload(0x740), mload(0x2160), f_q)) +mstore(0x21a0, addmod(mload(0x2180), mload(0x3c0), f_q)) +mstore(0x21c0, mulmod(mload(0x8e0), mload(0x360), f_q)) +mstore(0x21e0, addmod(mload(0x7c0), mload(0x21c0), f_q)) +mstore(0x2200, addmod(mload(0x21e0), mload(0x3c0), f_q)) +mstore(0x2220, mulmod(mload(0x2200), mload(0x21a0), f_q)) +mstore(0x2240, mulmod(mload(0x2220), mload(0x9a0), f_q)) +mstore(0x2260, mulmod(8910878055287538404433155982483128285667088683464058436815641868457422632747, mload(0x360), f_q)) +mstore(0x2280, mulmod(mload(0x680), mload(0x2260), f_q)) +mstore(0x22a0, addmod(mload(0x740), mload(0x2280), f_q)) +mstore(0x22c0, addmod(mload(0x22a0), mload(0x3c0), f_q)) +mstore(0x22e0, mulmod(11166246659983828508719468090013646171463329086121580628794302409516816350802, mload(0x360), f_q)) +mstore(0x2300, mulmod(mload(0x680), mload(0x22e0), f_q)) +mstore(0x2320, addmod(mload(0x7c0), mload(0x2300), f_q)) +mstore(0x2340, addmod(mload(0x2320), mload(0x3c0), f_q)) +mstore(0x2360, mulmod(mload(0x2340), mload(0x22c0), f_q)) +mstore(0x2380, mulmod(mload(0x2360), mload(0x980), f_q)) +mstore(0x23a0, addmod(mload(0x2240), sub(f_q, mload(0x2380)), f_q)) +mstore(0x23c0, mulmod(mload(0x23a0), mload(0x1e80), f_q)) +mstore(0x23e0, addmod(mload(0x2140), mload(0x23c0), f_q)) +mstore(0x2400, mulmod(mload(0x560), mload(0x23e0), f_q)) +mstore(0x2420, mulmod(mload(0x900), mload(0x360), f_q)) +mstore(0x2440, addmod(mload(0x1a20), mload(0x2420), f_q)) +mstore(0x2460, addmod(mload(0x2440), mload(0x3c0), f_q)) +mstore(0x2480, mulmod(mload(0x2460), mload(0xa00), f_q)) +mstore(0x24a0, mulmod(284840088355319032285349970403338060113257071685626700086398481893096618818, mload(0x360), f_q)) +mstore(0x24c0, mulmod(mload(0x680), mload(0x24a0), f_q)) +mstore(0x24e0, addmod(mload(0x1a20), mload(0x24c0), f_q)) +mstore(0x2500, addmod(mload(0x24e0), mload(0x3c0), f_q)) +mstore(0x2520, mulmod(mload(0x2500), mload(0x9e0), f_q)) +mstore(0x2540, addmod(mload(0x2480), sub(f_q, mload(0x2520)), f_q)) +mstore(0x2560, mulmod(mload(0x2540), mload(0x1e80), f_q)) +mstore(0x2580, addmod(mload(0x2400), mload(0x2560), f_q)) +mstore(0x25a0, mulmod(mload(0x560), mload(0x2580), f_q)) +mstore(0x25c0, addmod(1, sub(f_q, mload(0xa20)), f_q)) +mstore(0x25e0, mulmod(mload(0x25c0), mload(0x18a0), f_q)) +mstore(0x2600, addmod(mload(0x25a0), mload(0x25e0), f_q)) +mstore(0x2620, mulmod(mload(0x560), mload(0x2600), f_q)) +mstore(0x2640, mulmod(mload(0xa20), mload(0xa20), f_q)) +mstore(0x2660, addmod(mload(0x2640), sub(f_q, mload(0xa20)), f_q)) +mstore(0x2680, mulmod(mload(0x2660), mload(0x17c0), f_q)) +mstore(0x26a0, addmod(mload(0x2620), mload(0x2680), f_q)) +mstore(0x26c0, mulmod(mload(0x560), mload(0x26a0), f_q)) +mstore(0x26e0, addmod(mload(0xa60), mload(0x360), f_q)) +mstore(0x2700, mulmod(mload(0x26e0), mload(0xa40), f_q)) +mstore(0x2720, addmod(mload(0xaa0), mload(0x3c0), f_q)) +mstore(0x2740, mulmod(mload(0x2720), mload(0x2700), f_q)) +mstore(0x2760, addmod(mload(0x7c0), mload(0x360), f_q)) +mstore(0x2780, mulmod(mload(0x2760), mload(0xa20), f_q)) +mstore(0x27a0, addmod(mload(0x800), mload(0x3c0), f_q)) +mstore(0x27c0, mulmod(mload(0x27a0), mload(0x2780), f_q)) +mstore(0x27e0, addmod(mload(0x2740), sub(f_q, mload(0x27c0)), f_q)) +mstore(0x2800, mulmod(mload(0x27e0), mload(0x1e80), f_q)) +mstore(0x2820, addmod(mload(0x26c0), mload(0x2800), f_q)) +mstore(0x2840, mulmod(mload(0x560), mload(0x2820), f_q)) +mstore(0x2860, addmod(mload(0xa60), sub(f_q, mload(0xaa0)), f_q)) +mstore(0x2880, mulmod(mload(0x2860), mload(0x18a0), f_q)) +mstore(0x28a0, addmod(mload(0x2840), mload(0x2880), f_q)) +mstore(0x28c0, mulmod(mload(0x560), mload(0x28a0), f_q)) +mstore(0x28e0, mulmod(mload(0x2860), mload(0x1e80), f_q)) +mstore(0x2900, addmod(mload(0xa60), sub(f_q, mload(0xa80)), f_q)) +mstore(0x2920, mulmod(mload(0x2900), mload(0x28e0), f_q)) +mstore(0x2940, addmod(mload(0x28c0), mload(0x2920), f_q)) +mstore(0x2960, mulmod(mload(0xf60), mload(0xf60), f_q)) +mstore(0x2980, mulmod(mload(0x2960), mload(0xf60), f_q)) +mstore(0x29a0, mulmod(1, mload(0xf60), f_q)) +mstore(0x29c0, mulmod(1, mload(0x2960), f_q)) +mstore(0x29e0, mulmod(mload(0x2940), mload(0xf80), f_q)) +mstore(0x2a00, mulmod(mload(0xce0), mload(0x680), f_q)) +mstore(0x2a20, mulmod(mload(0x2a00), mload(0x680), f_q)) +mstore(0x2a40, mulmod(mload(0x680), 20975929243409798062839949658616274858986091382510192949221301676705706354487, f_q)) +mstore(0x2a60, addmod(mload(0xbe0), sub(f_q, mload(0x2a40)), f_q)) +mstore(0x2a80, mulmod(mload(0x680), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q)) +mstore(0x2aa0, addmod(mload(0xbe0), sub(f_q, mload(0x2a80)), f_q)) +mstore(0x2ac0, mulmod(mload(0x680), 1, f_q)) +mstore(0x2ae0, addmod(mload(0xbe0), sub(f_q, mload(0x2ac0)), f_q)) +mstore(0x2b00, mulmod(mload(0x680), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +mstore(0x2b20, addmod(mload(0xbe0), sub(f_q, mload(0x2b00)), f_q)) +mstore(0x2b40, mulmod(mload(0x680), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q)) +mstore(0x2b60, addmod(mload(0xbe0), sub(f_q, mload(0x2b40)), f_q)) +mstore(0x2b80, mulmod(mload(0x680), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q)) +mstore(0x2ba0, addmod(mload(0xbe0), sub(f_q, mload(0x2b80)), f_q)) +mstore(0x2bc0, mulmod(12142985201493934370659158242092015678465417407805993602870272259656026591649, mload(0x2a00), f_q)) +mstore(0x2be0, mulmod(mload(0x2bc0), 1, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2bc0), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x2be0)), f_q), result, f_q) +mstore(11264, result) + } +mstore(0x2c20, mulmod(12858672892267984631233883117647866851148059157064290846881981435700301865966, mload(0x2a00), f_q)) +mstore(0x2c40, mulmod(mload(0x2c20), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2c20), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x2c40)), f_q), result, f_q) +mstore(11360, result) + } +mstore(0x2c80, mulmod(20880316823902385764034220950270964645276820671488089374347912013802613180902, mload(0x2a00), f_q)) +mstore(0x2ca0, mulmod(mload(0x2c80), 19032961837237948602743626455740240236231119053033140765040043513661803148152, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2c80), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x2ca0)), f_q), result, f_q) +mstore(11456, result) + } +mstore(0x2ce0, mulmod(17575202995145968412995467587554373308969396527144859871466654432792864477050, mload(0x2a00), f_q)) +mstore(0x2d00, mulmod(mload(0x2ce0), 3766081621734395783232337525162072736827576297943013392955872170138036189193, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2ce0), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x2d00)), f_q), result, f_q) +mstore(11552, result) + } +mstore(0x2d40, mulmod(1, mload(0x2ae0), f_q)) +mstore(0x2d60, mulmod(mload(0x2d40), mload(0x2b20), f_q)) +mstore(0x2d80, mulmod(mload(0x2d60), mload(0x2b60), f_q)) +mstore(0x2da0, mulmod(mload(0x2d80), mload(0x2ba0), f_q)) +{ + let result := mulmod(mload(0xbe0), 1, f_q) +result := addmod(mulmod(mload(0x680), 21888242871839275222246405745257275088548364400416034343698204186575808495616, f_q), result, f_q) +mstore(11712, result) + } +mstore(0x2de0, mulmod(21869340487638379139105209872801492456082780734504032269410146788560475001942, mload(0xce0), f_q)) +mstore(0x2e00, mulmod(mload(0x2de0), 1, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2de0), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x2e00)), f_q), result, f_q) +mstore(11808, result) + } +mstore(0x2e40, mulmod(16199055355995875908874098831560099797649990976433931925532505422809603664814, mload(0xce0), f_q)) +mstore(0x2e60, mulmod(mload(0x2e40), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2e40), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x2e60)), f_q), result, f_q) +mstore(11904, result) + } +mstore(0x2ea0, mulmod(4865187280763976036134135047793386535665014353502380106898040096680231678680, mload(0xce0), f_q)) +mstore(0x2ec0, mulmod(mload(0x2ea0), 20975929243409798062839949658616274858986091382510192949221301676705706354487, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2ea0), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x2ec0)), f_q), result, f_q) +mstore(12000, result) + } +mstore(0x2f00, mulmod(mload(0x2d60), mload(0x2a60), f_q)) +mstore(0x2f20, mulmod(20461838439117790833741043996939313553025008529160428886800406442142042007111, mload(0x680), f_q)) +mstore(0x2f40, mulmod(mload(0x2f20), 1, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2f20), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x2f40)), f_q), result, f_q) +mstore(12128, result) + } +mstore(0x2f80, mulmod(1426404432721484388505361748317961535523355871255605456897797744433766488506, mload(0x680), f_q)) +mstore(0x2fa0, mulmod(mload(0x2f80), 1426404432721484388505361748317961535523355871255605456897797744433766488507, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2f80), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x2fa0)), f_q), result, f_q) +mstore(12224, result) + } +mstore(0x2fe0, mulmod(19102728315457599142069468034376470979900453007937332237837518576196438670602, mload(0x680), f_q)) +mstore(0x3000, mulmod(mload(0x2fe0), 1, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x2fe0), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x3000)), f_q), result, f_q) +mstore(12320, result) + } +mstore(0x3040, mulmod(2785514556381676080176937710880804108647911392478702105860685610379369825015, mload(0x680), f_q)) +mstore(0x3060, mulmod(mload(0x3040), 2785514556381676080176937710880804108647911392478702105860685610379369825016, f_q)) +{ + let result := mulmod(mload(0xbe0), mload(0x3040), f_q) +result := addmod(mulmod(mload(0x680), sub(f_q, mload(0x3060)), f_q), result, f_q) +mstore(12416, result) + } +mstore(0x30a0, mulmod(mload(0x2d40), mload(0x2aa0), f_q)) +{ + let prod := mload(0x2c00) + + prod := mulmod(mload(0x2c60), prod, f_q) + mstore(0x30c0, prod) + + prod := mulmod(mload(0x2cc0), prod, f_q) + mstore(0x30e0, prod) + + prod := mulmod(mload(0x2d20), prod, f_q) + mstore(0x3100, prod) + + prod := mulmod(mload(0x2dc0), prod, f_q) + mstore(0x3120, prod) + + prod := mulmod(mload(0x2d40), prod, f_q) + mstore(0x3140, prod) + + prod := mulmod(mload(0x2e20), prod, f_q) + mstore(0x3160, prod) + + prod := mulmod(mload(0x2e80), prod, f_q) + mstore(0x3180, prod) + + prod := mulmod(mload(0x2ee0), prod, f_q) + mstore(0x31a0, prod) + + prod := mulmod(mload(0x2f00), prod, f_q) + mstore(0x31c0, prod) + + prod := mulmod(mload(0x2f60), prod, f_q) + mstore(0x31e0, prod) + + prod := mulmod(mload(0x2fc0), prod, f_q) + mstore(0x3200, prod) + + prod := mulmod(mload(0x2d60), prod, f_q) + mstore(0x3220, prod) + + prod := mulmod(mload(0x3020), prod, f_q) + mstore(0x3240, prod) + + prod := mulmod(mload(0x3080), prod, f_q) + mstore(0x3260, prod) + + prod := mulmod(mload(0x30a0), prod, f_q) + mstore(0x3280, prod) + + } +mstore(0x32c0, 32) +mstore(0x32e0, 32) +mstore(0x3300, 32) +mstore(0x3320, mload(0x3280)) +mstore(0x3340, 21888242871839275222246405745257275088548364400416034343698204186575808495615) +mstore(0x3360, 21888242871839275222246405745257275088548364400416034343698204186575808495617) +success := and(eq(staticcall(gas(), 0x5, 0x32c0, 0xc0, 0x32a0, 0x20), 1), success) +{ + + let inv := mload(0x32a0) + let v + + v := mload(0x30a0) + mstore(12448, mulmod(mload(0x3260), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3080) + mstore(12416, mulmod(mload(0x3240), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3020) + mstore(12320, mulmod(mload(0x3220), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2d60) + mstore(11616, mulmod(mload(0x3200), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2fc0) + mstore(12224, mulmod(mload(0x31e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2f60) + mstore(12128, mulmod(mload(0x31c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2f00) + mstore(12032, mulmod(mload(0x31a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2ee0) + mstore(12000, mulmod(mload(0x3180), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2e80) + mstore(11904, mulmod(mload(0x3160), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2e20) + mstore(11808, mulmod(mload(0x3140), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2d40) + mstore(11584, mulmod(mload(0x3120), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2dc0) + mstore(11712, mulmod(mload(0x3100), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2d20) + mstore(11552, mulmod(mload(0x30e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2cc0) + mstore(11456, mulmod(mload(0x30c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x2c60) + mstore(11360, mulmod(mload(0x2c00), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0x2c00, inv) + + } +{ + let result := mload(0x2c00) +result := addmod(mload(0x2c60), result, f_q) +result := addmod(mload(0x2cc0), result, f_q) +result := addmod(mload(0x2d20), result, f_q) +mstore(13184, result) + } +mstore(0x33a0, mulmod(mload(0x2da0), mload(0x2d40), f_q)) +{ + let result := mload(0x2dc0) +mstore(13248, result) + } +mstore(0x33e0, mulmod(mload(0x2da0), mload(0x2f00), f_q)) +{ + let result := mload(0x2e20) +result := addmod(mload(0x2e80), result, f_q) +result := addmod(mload(0x2ee0), result, f_q) +mstore(13312, result) + } +mstore(0x3420, mulmod(mload(0x2da0), mload(0x2d60), f_q)) +{ + let result := mload(0x2f60) +result := addmod(mload(0x2fc0), result, f_q) +mstore(13376, result) + } +mstore(0x3460, mulmod(mload(0x2da0), mload(0x30a0), f_q)) +{ + let result := mload(0x3020) +result := addmod(mload(0x3080), result, f_q) +mstore(13440, result) + } +{ + let prod := mload(0x3380) + + prod := mulmod(mload(0x33c0), prod, f_q) + mstore(0x34a0, prod) + + prod := mulmod(mload(0x3400), prod, f_q) + mstore(0x34c0, prod) + + prod := mulmod(mload(0x3440), prod, f_q) + mstore(0x34e0, prod) + + prod := mulmod(mload(0x3480), prod, f_q) + mstore(0x3500, prod) + + } +mstore(0x3540, 32) +mstore(0x3560, 32) +mstore(0x3580, 32) +mstore(0x35a0, mload(0x3500)) +mstore(0x35c0, 21888242871839275222246405745257275088548364400416034343698204186575808495615) +mstore(0x35e0, 21888242871839275222246405745257275088548364400416034343698204186575808495617) +success := and(eq(staticcall(gas(), 0x5, 0x3540, 0xc0, 0x3520, 0x20), 1), success) +{ + + let inv := mload(0x3520) + let v + + v := mload(0x3480) + mstore(13440, mulmod(mload(0x34e0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3440) + mstore(13376, mulmod(mload(0x34c0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x3400) + mstore(13312, mulmod(mload(0x34a0), inv, f_q)) + inv := mulmod(v, inv, f_q) + + v := mload(0x33c0) + mstore(13248, mulmod(mload(0x3380), inv, f_q)) + inv := mulmod(v, inv, f_q) + mstore(0x3380, inv) + + } +mstore(0x3600, mulmod(mload(0x33a0), mload(0x33c0), f_q)) +mstore(0x3620, mulmod(mload(0x33e0), mload(0x3400), f_q)) +mstore(0x3640, mulmod(mload(0x3420), mload(0x3440), f_q)) +mstore(0x3660, mulmod(mload(0x3460), mload(0x3480), f_q)) +mstore(0x3680, mulmod(mload(0xae0), mload(0xae0), f_q)) +mstore(0x36a0, mulmod(mload(0x3680), mload(0xae0), f_q)) +mstore(0x36c0, mulmod(mload(0x36a0), mload(0xae0), f_q)) +mstore(0x36e0, mulmod(mload(0x36c0), mload(0xae0), f_q)) +mstore(0x3700, mulmod(mload(0x36e0), mload(0xae0), f_q)) +mstore(0x3720, mulmod(mload(0x3700), mload(0xae0), f_q)) +mstore(0x3740, mulmod(mload(0x3720), mload(0xae0), f_q)) +mstore(0x3760, mulmod(mload(0x3740), mload(0xae0), f_q)) +mstore(0x3780, mulmod(mload(0x3760), mload(0xae0), f_q)) +mstore(0x37a0, mulmod(mload(0x3780), mload(0xae0), f_q)) +mstore(0x37c0, mulmod(mload(0x37a0), mload(0xae0), f_q)) +mstore(0x37e0, mulmod(mload(0x37c0), mload(0xae0), f_q)) +mstore(0x3800, mulmod(mload(0xb40), mload(0xb40), f_q)) +mstore(0x3820, mulmod(mload(0x3800), mload(0xb40), f_q)) +mstore(0x3840, mulmod(mload(0x3820), mload(0xb40), f_q)) +mstore(0x3860, mulmod(mload(0x3840), mload(0xb40), f_q)) +{ + let result := mulmod(mload(0x6c0), mload(0x2c00), f_q) +result := addmod(mulmod(mload(0x6e0), mload(0x2c60), f_q), result, f_q) +result := addmod(mulmod(mload(0x700), mload(0x2cc0), f_q), result, f_q) +result := addmod(mulmod(mload(0x720), mload(0x2d20), f_q), result, f_q) +mstore(14464, result) + } +mstore(0x38a0, mulmod(mload(0x3880), mload(0x3380), f_q)) +mstore(0x38c0, mulmod(sub(f_q, mload(0x38a0)), 1, f_q)) +{ + let result := mulmod(mload(0x740), mload(0x2c00), f_q) +result := addmod(mulmod(mload(0x760), mload(0x2c60), f_q), result, f_q) +result := addmod(mulmod(mload(0x780), mload(0x2cc0), f_q), result, f_q) +result := addmod(mulmod(mload(0x7a0), mload(0x2d20), f_q), result, f_q) +mstore(14560, result) + } +mstore(0x3900, mulmod(mload(0x38e0), mload(0x3380), f_q)) +mstore(0x3920, mulmod(sub(f_q, mload(0x3900)), mload(0xae0), f_q)) +mstore(0x3940, mulmod(1, mload(0xae0), f_q)) +mstore(0x3960, addmod(mload(0x38c0), mload(0x3920), f_q)) +mstore(0x3980, mulmod(mload(0x3960), 1, f_q)) +mstore(0x39a0, mulmod(mload(0x3940), 1, f_q)) +mstore(0x39c0, mulmod(1, mload(0x33a0), f_q)) +{ + let result := mulmod(mload(0x7c0), mload(0x2dc0), f_q) +mstore(14816, result) + } +mstore(0x3a00, mulmod(mload(0x39e0), mload(0x3600), f_q)) +mstore(0x3a20, mulmod(sub(f_q, mload(0x3a00)), 1, f_q)) +mstore(0x3a40, mulmod(mload(0x39c0), 1, f_q)) +{ + let result := mulmod(mload(0xaa0), mload(0x2dc0), f_q) +mstore(14944, result) + } +mstore(0x3a80, mulmod(mload(0x3a60), mload(0x3600), f_q)) +mstore(0x3aa0, mulmod(sub(f_q, mload(0x3a80)), mload(0xae0), f_q)) +mstore(0x3ac0, mulmod(mload(0x39c0), mload(0xae0), f_q)) +mstore(0x3ae0, addmod(mload(0x3a20), mload(0x3aa0), f_q)) +{ + let result := mulmod(mload(0x7e0), mload(0x2dc0), f_q) +mstore(15104, result) + } +mstore(0x3b20, mulmod(mload(0x3b00), mload(0x3600), f_q)) +mstore(0x3b40, mulmod(sub(f_q, mload(0x3b20)), mload(0x3680), f_q)) +mstore(0x3b60, mulmod(mload(0x39c0), mload(0x3680), f_q)) +mstore(0x3b80, addmod(mload(0x3ae0), mload(0x3b40), f_q)) +{ + let result := mulmod(mload(0x800), mload(0x2dc0), f_q) +mstore(15264, result) + } +mstore(0x3bc0, mulmod(mload(0x3ba0), mload(0x3600), f_q)) +mstore(0x3be0, mulmod(sub(f_q, mload(0x3bc0)), mload(0x36a0), f_q)) +mstore(0x3c00, mulmod(mload(0x39c0), mload(0x36a0), f_q)) +mstore(0x3c20, addmod(mload(0x3b80), mload(0x3be0), f_q)) +{ + let result := mulmod(mload(0x820), mload(0x2dc0), f_q) +mstore(15424, result) + } +mstore(0x3c60, mulmod(mload(0x3c40), mload(0x3600), f_q)) +mstore(0x3c80, mulmod(sub(f_q, mload(0x3c60)), mload(0x36c0), f_q)) +mstore(0x3ca0, mulmod(mload(0x39c0), mload(0x36c0), f_q)) +mstore(0x3cc0, addmod(mload(0x3c20), mload(0x3c80), f_q)) +{ + let result := mulmod(mload(0x840), mload(0x2dc0), f_q) +mstore(15584, result) + } +mstore(0x3d00, mulmod(mload(0x3ce0), mload(0x3600), f_q)) +mstore(0x3d20, mulmod(sub(f_q, mload(0x3d00)), mload(0x36e0), f_q)) +mstore(0x3d40, mulmod(mload(0x39c0), mload(0x36e0), f_q)) +mstore(0x3d60, addmod(mload(0x3cc0), mload(0x3d20), f_q)) +{ + let result := mulmod(mload(0x880), mload(0x2dc0), f_q) +mstore(15744, result) + } +mstore(0x3da0, mulmod(mload(0x3d80), mload(0x3600), f_q)) +mstore(0x3dc0, mulmod(sub(f_q, mload(0x3da0)), mload(0x3700), f_q)) +mstore(0x3de0, mulmod(mload(0x39c0), mload(0x3700), f_q)) +mstore(0x3e00, addmod(mload(0x3d60), mload(0x3dc0), f_q)) +{ + let result := mulmod(mload(0x8a0), mload(0x2dc0), f_q) +mstore(15904, result) + } +mstore(0x3e40, mulmod(mload(0x3e20), mload(0x3600), f_q)) +mstore(0x3e60, mulmod(sub(f_q, mload(0x3e40)), mload(0x3720), f_q)) +mstore(0x3e80, mulmod(mload(0x39c0), mload(0x3720), f_q)) +mstore(0x3ea0, addmod(mload(0x3e00), mload(0x3e60), f_q)) +{ + let result := mulmod(mload(0x8c0), mload(0x2dc0), f_q) +mstore(16064, result) + } +mstore(0x3ee0, mulmod(mload(0x3ec0), mload(0x3600), f_q)) +mstore(0x3f00, mulmod(sub(f_q, mload(0x3ee0)), mload(0x3740), f_q)) +mstore(0x3f20, mulmod(mload(0x39c0), mload(0x3740), f_q)) +mstore(0x3f40, addmod(mload(0x3ea0), mload(0x3f00), f_q)) +{ + let result := mulmod(mload(0x8e0), mload(0x2dc0), f_q) +mstore(16224, result) + } +mstore(0x3f80, mulmod(mload(0x3f60), mload(0x3600), f_q)) +mstore(0x3fa0, mulmod(sub(f_q, mload(0x3f80)), mload(0x3760), f_q)) +mstore(0x3fc0, mulmod(mload(0x39c0), mload(0x3760), f_q)) +mstore(0x3fe0, addmod(mload(0x3f40), mload(0x3fa0), f_q)) +{ + let result := mulmod(mload(0x900), mload(0x2dc0), f_q) +mstore(16384, result) + } +mstore(0x4020, mulmod(mload(0x4000), mload(0x3600), f_q)) +mstore(0x4040, mulmod(sub(f_q, mload(0x4020)), mload(0x3780), f_q)) +mstore(0x4060, mulmod(mload(0x39c0), mload(0x3780), f_q)) +mstore(0x4080, addmod(mload(0x3fe0), mload(0x4040), f_q)) +mstore(0x40a0, mulmod(mload(0x29a0), mload(0x33a0), f_q)) +mstore(0x40c0, mulmod(mload(0x29c0), mload(0x33a0), f_q)) +{ + let result := mulmod(mload(0x29e0), mload(0x2dc0), f_q) +mstore(16608, result) + } +mstore(0x4100, mulmod(mload(0x40e0), mload(0x3600), f_q)) +mstore(0x4120, mulmod(sub(f_q, mload(0x4100)), mload(0x37a0), f_q)) +mstore(0x4140, mulmod(mload(0x39c0), mload(0x37a0), f_q)) +mstore(0x4160, mulmod(mload(0x40a0), mload(0x37a0), f_q)) +mstore(0x4180, mulmod(mload(0x40c0), mload(0x37a0), f_q)) +mstore(0x41a0, addmod(mload(0x4080), mload(0x4120), f_q)) +{ + let result := mulmod(mload(0x860), mload(0x2dc0), f_q) +mstore(16832, result) + } +mstore(0x41e0, mulmod(mload(0x41c0), mload(0x3600), f_q)) +mstore(0x4200, mulmod(sub(f_q, mload(0x41e0)), mload(0x37c0), f_q)) +mstore(0x4220, mulmod(mload(0x39c0), mload(0x37c0), f_q)) +mstore(0x4240, addmod(mload(0x41a0), mload(0x4200), f_q)) +mstore(0x4260, mulmod(mload(0x4240), mload(0xb40), f_q)) +mstore(0x4280, mulmod(mload(0x3a40), mload(0xb40), f_q)) +mstore(0x42a0, mulmod(mload(0x3ac0), mload(0xb40), f_q)) +mstore(0x42c0, mulmod(mload(0x3b60), mload(0xb40), f_q)) +mstore(0x42e0, mulmod(mload(0x3c00), mload(0xb40), f_q)) +mstore(0x4300, mulmod(mload(0x3ca0), mload(0xb40), f_q)) +mstore(0x4320, mulmod(mload(0x3d40), mload(0xb40), f_q)) +mstore(0x4340, mulmod(mload(0x3de0), mload(0xb40), f_q)) +mstore(0x4360, mulmod(mload(0x3e80), mload(0xb40), f_q)) +mstore(0x4380, mulmod(mload(0x3f20), mload(0xb40), f_q)) +mstore(0x43a0, mulmod(mload(0x3fc0), mload(0xb40), f_q)) +mstore(0x43c0, mulmod(mload(0x4060), mload(0xb40), f_q)) +mstore(0x43e0, mulmod(mload(0x4140), mload(0xb40), f_q)) +mstore(0x4400, mulmod(mload(0x4160), mload(0xb40), f_q)) +mstore(0x4420, mulmod(mload(0x4180), mload(0xb40), f_q)) +mstore(0x4440, mulmod(mload(0x4220), mload(0xb40), f_q)) +mstore(0x4460, addmod(mload(0x3980), mload(0x4260), f_q)) +mstore(0x4480, mulmod(1, mload(0x33e0), f_q)) +{ + let result := mulmod(mload(0x920), mload(0x2e20), f_q) +result := addmod(mulmod(mload(0x940), mload(0x2e80), f_q), result, f_q) +result := addmod(mulmod(mload(0x960), mload(0x2ee0), f_q), result, f_q) +mstore(17568, result) + } +mstore(0x44c0, mulmod(mload(0x44a0), mload(0x3620), f_q)) +mstore(0x44e0, mulmod(sub(f_q, mload(0x44c0)), 1, f_q)) +mstore(0x4500, mulmod(mload(0x4480), 1, f_q)) +{ + let result := mulmod(mload(0x980), mload(0x2e20), f_q) +result := addmod(mulmod(mload(0x9a0), mload(0x2e80), f_q), result, f_q) +result := addmod(mulmod(mload(0x9c0), mload(0x2ee0), f_q), result, f_q) +mstore(17696, result) + } +mstore(0x4540, mulmod(mload(0x4520), mload(0x3620), f_q)) +mstore(0x4560, mulmod(sub(f_q, mload(0x4540)), mload(0xae0), f_q)) +mstore(0x4580, mulmod(mload(0x4480), mload(0xae0), f_q)) +mstore(0x45a0, addmod(mload(0x44e0), mload(0x4560), f_q)) +mstore(0x45c0, mulmod(mload(0x45a0), mload(0x3800), f_q)) +mstore(0x45e0, mulmod(mload(0x4500), mload(0x3800), f_q)) +mstore(0x4600, mulmod(mload(0x4580), mload(0x3800), f_q)) +mstore(0x4620, addmod(mload(0x4460), mload(0x45c0), f_q)) +mstore(0x4640, mulmod(1, mload(0x3420), f_q)) +{ + let result := mulmod(mload(0x9e0), mload(0x2f60), f_q) +result := addmod(mulmod(mload(0xa00), mload(0x2fc0), f_q), result, f_q) +mstore(18016, result) + } +mstore(0x4680, mulmod(mload(0x4660), mload(0x3640), f_q)) +mstore(0x46a0, mulmod(sub(f_q, mload(0x4680)), 1, f_q)) +mstore(0x46c0, mulmod(mload(0x4640), 1, f_q)) +{ + let result := mulmod(mload(0xa20), mload(0x2f60), f_q) +result := addmod(mulmod(mload(0xa40), mload(0x2fc0), f_q), result, f_q) +mstore(18144, result) + } +mstore(0x4700, mulmod(mload(0x46e0), mload(0x3640), f_q)) +mstore(0x4720, mulmod(sub(f_q, mload(0x4700)), mload(0xae0), f_q)) +mstore(0x4740, mulmod(mload(0x4640), mload(0xae0), f_q)) +mstore(0x4760, addmod(mload(0x46a0), mload(0x4720), f_q)) +mstore(0x4780, mulmod(mload(0x4760), mload(0x3820), f_q)) +mstore(0x47a0, mulmod(mload(0x46c0), mload(0x3820), f_q)) +mstore(0x47c0, mulmod(mload(0x4740), mload(0x3820), f_q)) +mstore(0x47e0, addmod(mload(0x4620), mload(0x4780), f_q)) +mstore(0x4800, mulmod(1, mload(0x3460), f_q)) +{ + let result := mulmod(mload(0xa60), mload(0x3020), f_q) +result := addmod(mulmod(mload(0xa80), mload(0x3080), f_q), result, f_q) +mstore(18464, result) + } +mstore(0x4840, mulmod(mload(0x4820), mload(0x3660), f_q)) +mstore(0x4860, mulmod(sub(f_q, mload(0x4840)), 1, f_q)) +mstore(0x4880, mulmod(mload(0x4800), 1, f_q)) +mstore(0x48a0, mulmod(mload(0x4860), mload(0x3840), f_q)) +mstore(0x48c0, mulmod(mload(0x4880), mload(0x3840), f_q)) +mstore(0x48e0, addmod(mload(0x47e0), mload(0x48a0), f_q)) +mstore(0x4900, mulmod(1, mload(0x2da0), f_q)) +mstore(0x4920, mulmod(1, mload(0xbe0), f_q)) +mstore(0x4940, 0x0000000000000000000000000000000000000000000000000000000000000001) + mstore(0x4960, 0x0000000000000000000000000000000000000000000000000000000000000002) +mstore(0x4980, mload(0x48e0)) +success := and(eq(staticcall(gas(), 0x7, 0x4940, 0x60, 0x4940, 0x40), 1), success) +mstore(0x49a0, mload(0x4940)) + mstore(0x49c0, mload(0x4960)) +mstore(0x49e0, mload(0x1a0)) + mstore(0x4a00, mload(0x1c0)) +success := and(eq(staticcall(gas(), 0x6, 0x49a0, 0x80, 0x49a0, 0x40), 1), success) +mstore(0x4a20, mload(0x1e0)) + mstore(0x4a40, mload(0x200)) +mstore(0x4a60, mload(0x39a0)) +success := and(eq(staticcall(gas(), 0x7, 0x4a20, 0x60, 0x4a20, 0x40), 1), success) +mstore(0x4a80, mload(0x49a0)) + mstore(0x4aa0, mload(0x49c0)) +mstore(0x4ac0, mload(0x4a20)) + mstore(0x4ae0, mload(0x4a40)) +success := and(eq(staticcall(gas(), 0x6, 0x4a80, 0x80, 0x4a80, 0x40), 1), success) +mstore(0x4b00, mload(0x220)) + mstore(0x4b20, mload(0x240)) +mstore(0x4b40, mload(0x4280)) +success := and(eq(staticcall(gas(), 0x7, 0x4b00, 0x60, 0x4b00, 0x40), 1), success) +mstore(0x4b60, mload(0x4a80)) + mstore(0x4b80, mload(0x4aa0)) +mstore(0x4ba0, mload(0x4b00)) + mstore(0x4bc0, mload(0x4b20)) +success := and(eq(staticcall(gas(), 0x6, 0x4b60, 0x80, 0x4b60, 0x40), 1), success) +mstore(0x4be0, mload(0x300)) + mstore(0x4c00, mload(0x320)) +mstore(0x4c20, mload(0x42a0)) +success := and(eq(staticcall(gas(), 0x7, 0x4be0, 0x60, 0x4be0, 0x40), 1), success) +mstore(0x4c40, mload(0x4b60)) + mstore(0x4c60, mload(0x4b80)) +mstore(0x4c80, mload(0x4be0)) + mstore(0x4ca0, mload(0x4c00)) +success := and(eq(staticcall(gas(), 0x6, 0x4c40, 0x80, 0x4c40, 0x40), 1), success) +mstore(0x4cc0, 0x0a56bb24bdbd10b2ae380a0f6d2926afe21e55ef423d664a7093bdc47d7a970d) + mstore(0x4ce0, 0x3046067f3fbc66fb8322b30a454654489ad23370423a63caeab071e10143c65d) +mstore(0x4d00, mload(0x42c0)) +success := and(eq(staticcall(gas(), 0x7, 0x4cc0, 0x60, 0x4cc0, 0x40), 1), success) +mstore(0x4d20, mload(0x4c40)) + mstore(0x4d40, mload(0x4c60)) +mstore(0x4d60, mload(0x4cc0)) + mstore(0x4d80, mload(0x4ce0)) +success := and(eq(staticcall(gas(), 0x6, 0x4d20, 0x80, 0x4d20, 0x40), 1), success) +mstore(0x4da0, 0x165f42d12623508ec09f1a14ffe3841e636362840bcfe45fd4f0847a50968d91) + mstore(0x4dc0, 0x19664a50abfa10f51e0eb96bf39b959cd2ebd0ed52c60bc0d4e8535272a13ed9) +mstore(0x4de0, mload(0x42e0)) +success := and(eq(staticcall(gas(), 0x7, 0x4da0, 0x60, 0x4da0, 0x40), 1), success) +mstore(0x4e00, mload(0x4d20)) + mstore(0x4e20, mload(0x4d40)) +mstore(0x4e40, mload(0x4da0)) + mstore(0x4e60, mload(0x4dc0)) +success := and(eq(staticcall(gas(), 0x6, 0x4e00, 0x80, 0x4e00, 0x40), 1), success) +mstore(0x4e80, 0x0c7dc4e4516515f0050b10e6891a60f39ab7645bbf2134080574b9ae26a3fee2) + mstore(0x4ea0, 0x2ee3484a156715514bcc56f95e316bb23031b7460f679ebb427a7f8ad73aead2) +mstore(0x4ec0, mload(0x4300)) +success := and(eq(staticcall(gas(), 0x7, 0x4e80, 0x60, 0x4e80, 0x40), 1), success) +mstore(0x4ee0, mload(0x4e00)) + mstore(0x4f00, mload(0x4e20)) +mstore(0x4f20, mload(0x4e80)) + mstore(0x4f40, mload(0x4ea0)) +success := and(eq(staticcall(gas(), 0x6, 0x4ee0, 0x80, 0x4ee0, 0x40), 1), success) +mstore(0x4f60, 0x2fb1bc5dc1a8a163ac673f110c7ced2581955a8d47770fced15a66d8199a5c91) + mstore(0x4f80, 0x18f7802cf51055b658637bf93f53fcc4dbe4218c03cb54c9d3e74534e1b9cb8f) +mstore(0x4fa0, mload(0x4320)) +success := and(eq(staticcall(gas(), 0x7, 0x4f60, 0x60, 0x4f60, 0x40), 1), success) +mstore(0x4fc0, mload(0x4ee0)) + mstore(0x4fe0, mload(0x4f00)) +mstore(0x5000, mload(0x4f60)) + mstore(0x5020, mload(0x4f80)) +success := and(eq(staticcall(gas(), 0x6, 0x4fc0, 0x80, 0x4fc0, 0x40), 1), success) +mstore(0x5040, 0x2051ae2329a00ab4684564c9db909204379c6404686b9bb004253a0e87937c1a) + mstore(0x5060, 0x2228d27991956786c7b7ed829027a4268a8f57d342e507683aaaea7046a1721b) +mstore(0x5080, mload(0x4340)) +success := and(eq(staticcall(gas(), 0x7, 0x5040, 0x60, 0x5040, 0x40), 1), success) +mstore(0x50a0, mload(0x4fc0)) + mstore(0x50c0, mload(0x4fe0)) +mstore(0x50e0, mload(0x5040)) + mstore(0x5100, mload(0x5060)) +success := and(eq(staticcall(gas(), 0x6, 0x50a0, 0x80, 0x50a0, 0x40), 1), success) +mstore(0x5120, 0x144e8b5cd066532d7a019f3061d407aeb922b3a37125d39cee71a336088a8d57) + mstore(0x5140, 0x0465b8271620ef2988dbb05e0e32f58c14ee4aaec69263d36175afc35b129dc8) +mstore(0x5160, mload(0x4360)) +success := and(eq(staticcall(gas(), 0x7, 0x5120, 0x60, 0x5120, 0x40), 1), success) +mstore(0x5180, mload(0x50a0)) + mstore(0x51a0, mload(0x50c0)) +mstore(0x51c0, mload(0x5120)) + mstore(0x51e0, mload(0x5140)) +success := and(eq(staticcall(gas(), 0x6, 0x5180, 0x80, 0x5180, 0x40), 1), success) +mstore(0x5200, 0x2c5cb6e96533664432584b4373fc01286cb8aa2c8a7f05eac98fc5bc689e65bf) + mstore(0x5220, 0x2c6a00e02442db4548c0583842d7c460dfaba5a8ae3d86ca57b0d7c82d7090c8) +mstore(0x5240, mload(0x4380)) +success := and(eq(staticcall(gas(), 0x7, 0x5200, 0x60, 0x5200, 0x40), 1), success) +mstore(0x5260, mload(0x5180)) + mstore(0x5280, mload(0x51a0)) +mstore(0x52a0, mload(0x5200)) + mstore(0x52c0, mload(0x5220)) +success := and(eq(staticcall(gas(), 0x6, 0x5260, 0x80, 0x5260, 0x40), 1), success) +mstore(0x52e0, 0x2b737ba20cacc46db1394cb36a1cb92566946b943314b7037d038fbb83f233a8) + mstore(0x5300, 0x04dc42ddd6eb4c1c43a1175bc70c5b5c92577f968055708b4beeb22cea5cff99) +mstore(0x5320, mload(0x43a0)) +success := and(eq(staticcall(gas(), 0x7, 0x52e0, 0x60, 0x52e0, 0x40), 1), success) +mstore(0x5340, mload(0x5260)) + mstore(0x5360, mload(0x5280)) +mstore(0x5380, mload(0x52e0)) + mstore(0x53a0, mload(0x5300)) +success := and(eq(staticcall(gas(), 0x6, 0x5340, 0x80, 0x5340, 0x40), 1), success) +mstore(0x53c0, 0x0ff2ba345398269313967c25483b19e5e2de27f76a3a4357408c35dc42ddfec3) + mstore(0x53e0, 0x063d5c171abc02e7d09324a4f1bb6493d0584767678901f452ebc7f285037015) +mstore(0x5400, mload(0x43c0)) +success := and(eq(staticcall(gas(), 0x7, 0x53c0, 0x60, 0x53c0, 0x40), 1), success) +mstore(0x5420, mload(0x5340)) + mstore(0x5440, mload(0x5360)) +mstore(0x5460, mload(0x53c0)) + mstore(0x5480, mload(0x53e0)) +success := and(eq(staticcall(gas(), 0x6, 0x5420, 0x80, 0x5420, 0x40), 1), success) +mstore(0x54a0, mload(0x5a0)) + mstore(0x54c0, mload(0x5c0)) +mstore(0x54e0, mload(0x43e0)) +success := and(eq(staticcall(gas(), 0x7, 0x54a0, 0x60, 0x54a0, 0x40), 1), success) +mstore(0x5500, mload(0x5420)) + mstore(0x5520, mload(0x5440)) +mstore(0x5540, mload(0x54a0)) + mstore(0x5560, mload(0x54c0)) +success := and(eq(staticcall(gas(), 0x6, 0x5500, 0x80, 0x5500, 0x40), 1), success) +mstore(0x5580, mload(0x5e0)) + mstore(0x55a0, mload(0x600)) +mstore(0x55c0, mload(0x4400)) +success := and(eq(staticcall(gas(), 0x7, 0x5580, 0x60, 0x5580, 0x40), 1), success) +mstore(0x55e0, mload(0x5500)) + mstore(0x5600, mload(0x5520)) +mstore(0x5620, mload(0x5580)) + mstore(0x5640, mload(0x55a0)) +success := and(eq(staticcall(gas(), 0x6, 0x55e0, 0x80, 0x55e0, 0x40), 1), success) +mstore(0x5660, mload(0x620)) + mstore(0x5680, mload(0x640)) +mstore(0x56a0, mload(0x4420)) +success := and(eq(staticcall(gas(), 0x7, 0x5660, 0x60, 0x5660, 0x40), 1), success) +mstore(0x56c0, mload(0x55e0)) + mstore(0x56e0, mload(0x5600)) +mstore(0x5700, mload(0x5660)) + mstore(0x5720, mload(0x5680)) +success := and(eq(staticcall(gas(), 0x6, 0x56c0, 0x80, 0x56c0, 0x40), 1), success) +mstore(0x5740, mload(0x500)) + mstore(0x5760, mload(0x520)) +mstore(0x5780, mload(0x4440)) +success := and(eq(staticcall(gas(), 0x7, 0x5740, 0x60, 0x5740, 0x40), 1), success) +mstore(0x57a0, mload(0x56c0)) + mstore(0x57c0, mload(0x56e0)) +mstore(0x57e0, mload(0x5740)) + mstore(0x5800, mload(0x5760)) +success := and(eq(staticcall(gas(), 0x6, 0x57a0, 0x80, 0x57a0, 0x40), 1), success) +mstore(0x5820, mload(0x400)) + mstore(0x5840, mload(0x420)) +mstore(0x5860, mload(0x45e0)) +success := and(eq(staticcall(gas(), 0x7, 0x5820, 0x60, 0x5820, 0x40), 1), success) +mstore(0x5880, mload(0x57a0)) + mstore(0x58a0, mload(0x57c0)) +mstore(0x58c0, mload(0x5820)) + mstore(0x58e0, mload(0x5840)) +success := and(eq(staticcall(gas(), 0x6, 0x5880, 0x80, 0x5880, 0x40), 1), success) +mstore(0x5900, mload(0x440)) + mstore(0x5920, mload(0x460)) +mstore(0x5940, mload(0x4600)) +success := and(eq(staticcall(gas(), 0x7, 0x5900, 0x60, 0x5900, 0x40), 1), success) +mstore(0x5960, mload(0x5880)) + mstore(0x5980, mload(0x58a0)) +mstore(0x59a0, mload(0x5900)) + mstore(0x59c0, mload(0x5920)) +success := and(eq(staticcall(gas(), 0x6, 0x5960, 0x80, 0x5960, 0x40), 1), success) +mstore(0x59e0, mload(0x480)) + mstore(0x5a00, mload(0x4a0)) +mstore(0x5a20, mload(0x47a0)) +success := and(eq(staticcall(gas(), 0x7, 0x59e0, 0x60, 0x59e0, 0x40), 1), success) +mstore(0x5a40, mload(0x5960)) + mstore(0x5a60, mload(0x5980)) +mstore(0x5a80, mload(0x59e0)) + mstore(0x5aa0, mload(0x5a00)) +success := and(eq(staticcall(gas(), 0x6, 0x5a40, 0x80, 0x5a40, 0x40), 1), success) +mstore(0x5ac0, mload(0x4c0)) + mstore(0x5ae0, mload(0x4e0)) +mstore(0x5b00, mload(0x47c0)) +success := and(eq(staticcall(gas(), 0x7, 0x5ac0, 0x60, 0x5ac0, 0x40), 1), success) +mstore(0x5b20, mload(0x5a40)) + mstore(0x5b40, mload(0x5a60)) +mstore(0x5b60, mload(0x5ac0)) + mstore(0x5b80, mload(0x5ae0)) +success := and(eq(staticcall(gas(), 0x6, 0x5b20, 0x80, 0x5b20, 0x40), 1), success) +mstore(0x5ba0, mload(0x2c0)) + mstore(0x5bc0, mload(0x2e0)) +mstore(0x5be0, mload(0x48c0)) +success := and(eq(staticcall(gas(), 0x7, 0x5ba0, 0x60, 0x5ba0, 0x40), 1), success) +mstore(0x5c00, mload(0x5b20)) + mstore(0x5c20, mload(0x5b40)) +mstore(0x5c40, mload(0x5ba0)) + mstore(0x5c60, mload(0x5bc0)) +success := and(eq(staticcall(gas(), 0x6, 0x5c00, 0x80, 0x5c00, 0x40), 1), success) +mstore(0x5c80, mload(0xb80)) + mstore(0x5ca0, mload(0xba0)) +mstore(0x5cc0, sub(f_q, mload(0x4900))) +success := and(eq(staticcall(gas(), 0x7, 0x5c80, 0x60, 0x5c80, 0x40), 1), success) +mstore(0x5ce0, mload(0x5c00)) + mstore(0x5d00, mload(0x5c20)) +mstore(0x5d20, mload(0x5c80)) + mstore(0x5d40, mload(0x5ca0)) +success := and(eq(staticcall(gas(), 0x6, 0x5ce0, 0x80, 0x5ce0, 0x40), 1), success) +mstore(0x5d60, mload(0xc20)) + mstore(0x5d80, mload(0xc40)) +mstore(0x5da0, mload(0x4920)) +success := and(eq(staticcall(gas(), 0x7, 0x5d60, 0x60, 0x5d60, 0x40), 1), success) +mstore(0x5dc0, mload(0x5ce0)) + mstore(0x5de0, mload(0x5d00)) +mstore(0x5e00, mload(0x5d60)) + mstore(0x5e20, mload(0x5d80)) +success := and(eq(staticcall(gas(), 0x6, 0x5dc0, 0x80, 0x5dc0, 0x40), 1), success) +mstore(0x5e40, mload(0x5dc0)) + mstore(0x5e60, mload(0x5de0)) +mstore(0x5e80, mload(0xc20)) + mstore(0x5ea0, mload(0xc40)) +mstore(0x5ec0, mload(0xc60)) + mstore(0x5ee0, mload(0xc80)) +mstore(0x5f00, mload(0xca0)) + mstore(0x5f20, mload(0xcc0)) +mstore(0x5f40, keccak256(0x5e40, 256)) +mstore(24416, mod(mload(24384), f_q)) +mstore(0x5f80, mulmod(mload(0x5f60), mload(0x5f60), f_q)) +mstore(0x5fa0, mulmod(1, mload(0x5f60), f_q)) +mstore(0x5fc0, mload(0x5ec0)) + mstore(0x5fe0, mload(0x5ee0)) +mstore(0x6000, mload(0x5fa0)) +success := and(eq(staticcall(gas(), 0x7, 0x5fc0, 0x60, 0x5fc0, 0x40), 1), success) +mstore(0x6020, mload(0x5e40)) + mstore(0x6040, mload(0x5e60)) +mstore(0x6060, mload(0x5fc0)) + mstore(0x6080, mload(0x5fe0)) +success := and(eq(staticcall(gas(), 0x6, 0x6020, 0x80, 0x6020, 0x40), 1), success) +mstore(0x60a0, mload(0x5f00)) + mstore(0x60c0, mload(0x5f20)) +mstore(0x60e0, mload(0x5fa0)) +success := and(eq(staticcall(gas(), 0x7, 0x60a0, 0x60, 0x60a0, 0x40), 1), success) +mstore(0x6100, mload(0x5e80)) + mstore(0x6120, mload(0x5ea0)) +mstore(0x6140, mload(0x60a0)) + mstore(0x6160, mload(0x60c0)) +success := and(eq(staticcall(gas(), 0x6, 0x6100, 0x80, 0x6100, 0x40), 1), success) +mstore(0x6180, mload(0x6020)) + mstore(0x61a0, mload(0x6040)) +mstore(0x61c0, 0x198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2) + mstore(0x61e0, 0x1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed) + mstore(0x6200, 0x090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b) + mstore(0x6220, 0x12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa) +mstore(0x6240, mload(0x6100)) + mstore(0x6260, mload(0x6120)) +mstore(0x6280, 0x138d5863615c12d3bd7d3fd007776d281a337f9d7f6dce23532100bb4bb5839d) + mstore(0x62a0, 0x0a3bb881671ee4e9238366e87f6598f0de356372ed3dc870766ec8ac005211e4) + mstore(0x62c0, 0x19c9d7d9c6e7ad2d9a0d5847ebdd2687c668939a202553ded2760d3eb8dbf559) + mstore(0x62e0, 0x198adb441818c42721c88c532ed13a5da1ebb78b85574d0b7326d8e6f4c1e25a) +success := and(eq(staticcall(gas(), 0x8, 0x6180, 0x180, 0x6180, 0x20), 1), success) +success := and(eq(mload(0x6180), 1), success) + + // Revert if anything fails + if iszero(success) { revert(0, 0) } + + // Return empty bytes on success + return(0, 0) + + } + } +} + \ No newline at end of file diff --git a/snark-verifier-sdk/examples/standard_plonk.rs b/snark-verifier-sdk/examples/standard_plonk.rs new file mode 100644 index 00000000..7ad9c971 --- /dev/null +++ b/snark-verifier-sdk/examples/standard_plonk.rs @@ -0,0 +1,216 @@ +use std::path::Path; + +use halo2_base::gates::circuit::CircuitBuilderStage; +use halo2_base::halo2_proofs; +use halo2_base::utils::fs::gen_srs; +use halo2_proofs::halo2curves as halo2_curves; +use halo2_proofs::{halo2curves::bn256::Bn256, poly::kzg::commitment::ParamsKZG}; +use rand::rngs::OsRng; +use snark_verifier_sdk::evm::{evm_verify, gen_evm_proof_shplonk, gen_evm_verifier_shplonk}; +use snark_verifier_sdk::halo2::aggregation::{AggregationConfigParams, VerifierUniversality}; +use snark_verifier_sdk::{ + gen_pk, + halo2::{aggregation::AggregationCircuit, gen_snark_shplonk}, + Snark, +}; +use snark_verifier_sdk::{CircuitExt, SHPLONK}; + +mod application { + use super::halo2_curves::bn256::Fr; + use super::halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance}, + poly::Rotation, + }; + use rand::RngCore; + use snark_verifier_sdk::CircuitExt; + + #[derive(Clone, Copy)] + pub struct StandardPlonkConfig { + a: Column, + b: Column, + c: Column, + q_a: Column, + q_b: Column, + q_c: Column, + q_ab: Column, + constant: Column, + #[allow(dead_code)] + instance: Column, + } + + impl StandardPlonkConfig { + fn configure(meta: &mut ConstraintSystem) -> Self { + let [a, b, c] = [(); 3].map(|_| meta.advice_column()); + let [q_a, q_b, q_c, q_ab, constant] = [(); 5].map(|_| meta.fixed_column()); + let instance = meta.instance_column(); + + [a, b, c].map(|column| meta.enable_equality(column)); + + meta.create_gate( + "q_a·a + q_b·b + q_c·c + q_ab·a·b + constant + instance = 0", + |meta| { + let [a, b, c] = + [a, b, c].map(|column| meta.query_advice(column, Rotation::cur())); + let [q_a, q_b, q_c, q_ab, constant] = [q_a, q_b, q_c, q_ab, constant] + .map(|column| meta.query_fixed(column, Rotation::cur())); + let instance = meta.query_instance(instance, Rotation::cur()); + Some( + q_a * a.clone() + + q_b * b.clone() + + q_c * c + + q_ab * a * b + + constant + + instance, + ) + }, + ); + + StandardPlonkConfig { a, b, c, q_a, q_b, q_c, q_ab, constant, instance } + } + } + + #[derive(Clone, Default)] + pub struct StandardPlonk(Fr); + + impl StandardPlonk { + pub fn rand(mut rng: R) -> Self { + Self(Fr::from(rng.next_u32() as u64)) + } + } + + impl CircuitExt for StandardPlonk { + fn num_instance(&self) -> Vec { + vec![1] + } + + fn instances(&self) -> Vec> { + vec![vec![self.0]] + } + } + + impl Circuit for StandardPlonk { + type Config = StandardPlonkConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + Self::default() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + meta.set_minimum_degree(4); + StandardPlonkConfig::configure(meta) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + layouter.assign_region( + || "", + |mut region| { + #[cfg(feature = "halo2-pse")] + { + region.assign_advice(|| "", config.a, 0, || Value::known(self.0))?; + region.assign_fixed(|| "", config.q_a, 0, || Value::known(-Fr::one()))?; + region.assign_advice( + || "", + config.a, + 1, + || Value::known(-Fr::from(5u64)), + )?; + for (idx, column) in (1..).zip([ + config.q_a, + config.q_b, + config.q_c, + config.q_ab, + config.constant, + ]) { + region.assign_fixed( + || "", + column, + 1, + || Value::known(Fr::from(idx as u64)), + )?; + } + let a = + region.assign_advice(|| "", config.a, 2, || Value::known(Fr::one()))?; + a.copy_advice(|| "", &mut region, config.b, 3)?; + a.copy_advice(|| "", &mut region, config.c, 4)?; + } + #[cfg(feature = "halo2-axiom")] + { + region.assign_advice(config.a, 0, Value::known(self.0)); + region.assign_fixed(config.q_a, 0, -Fr::one()); + region.assign_advice(config.a, 1, Value::known(-Fr::from(5u64))); + for (idx, column) in (1..).zip([ + config.q_a, + config.q_b, + config.q_c, + config.q_ab, + config.constant, + ]) { + region.assign_fixed(column, 1, Fr::from(idx as u64)); + } + + let a = region.assign_advice(config.a, 2, Value::known(Fr::one())); + a.copy_advice(&mut region, config.b, 3); + a.copy_advice(&mut region, config.c, 4); + } + + Ok(()) + }, + ) + } + } +} + +fn gen_application_snark(params: &ParamsKZG) -> Snark { + let circuit = application::StandardPlonk::rand(OsRng); + + let pk = gen_pk(params, &circuit, None); + gen_snark_shplonk(params, &pk, circuit, None::<&str>) +} + +fn main() { + let params_app = gen_srs(8); + + let k = 21u32; + let lookup_bits = k as usize - 1; + let params = gen_srs(k); + let snarks = [(); 1].map(|_| gen_application_snark(¶ms_app)); + + let mut agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Keygen, + AggregationConfigParams { degree: k, lookup_bits, ..Default::default() }, + ¶ms, + snarks.clone(), + VerifierUniversality::Full, + ); + let agg_config = agg_circuit.calculate_params(Some(10)); + + let pk = gen_pk(¶ms, &agg_circuit, None); + let break_points = agg_circuit.break_points(); + drop(agg_circuit); + + let agg_circuit = AggregationCircuit::new::( + CircuitBuilderStage::Prover, + agg_config, + ¶ms, + snarks.clone(), + VerifierUniversality::Full, + ) + .use_break_points(break_points); + let num_instances = agg_circuit.num_instance(); + let instances = agg_circuit.instances(); + let proof = gen_evm_proof_shplonk(¶ms, &pk, agg_circuit, instances.clone()); + + let deployment_code = gen_evm_verifier_shplonk::( + ¶ms, + pk.get_vk(), + num_instances, + Some(Path::new("examples/StandardPlonkVerifier.sol")), + ); + evm_verify(deployment_code, instances, proof); +} diff --git a/snark-verifier-sdk/src/evm.rs b/snark-verifier-sdk/src/evm.rs index 97b1b96e..d3b745fb 100644 --- a/snark-verifier-sdk/src/evm.rs +++ b/snark-verifier-sdk/src/evm.rs @@ -22,7 +22,7 @@ use itertools::Itertools; use rand::{rngs::StdRng, SeedableRng}; pub use snark_verifier::loader::evm::encode_calldata; use snark_verifier::{ - loader::evm::{compile_yul, deploy_and_call, EvmLoader}, + loader::evm::{compile_solidity, deploy_and_call, EvmLoader}, pcs::{ kzg::{KzgAccumulator, KzgAsVerifyingKey, KzgDecidingKey, KzgSuccinctVerifyingKey}, AccumulationDecider, AccumulationScheme, PolynomialCommitmentScheme, @@ -147,11 +147,11 @@ where PlonkVerifier::::read_proof(&dk, &protocol, &instances, &mut transcript).unwrap(); PlonkVerifier::::verify(&dk, &protocol, &instances, &proof).unwrap(); - let yul_code = loader.yul_code(); - let byte_code = compile_yul(&yul_code); + let sol_code = loader.solidity_code(); + let byte_code = compile_solidity(&sol_code); if let Some(path) = path { path.parent().and_then(|dir| fs::create_dir_all(dir).ok()).unwrap(); - fs::write(path, yul_code).unwrap(); + fs::write(path, sol_code).unwrap(); } byte_code } diff --git a/snark-verifier/Cargo.toml b/snark-verifier/Cargo.toml index 2fbe6682..2321caa0 100644 --- a/snark-verifier/Cargo.toml +++ b/snark-verifier/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "snark-verifier" -version = "0.1.5" +version = "0.1.6" edition = "2021" [dependencies] diff --git a/snark-verifier/examples/evm-verifier-with-accumulator.rs b/snark-verifier/examples/evm-verifier-with-accumulator.rs index 645c71fd..304b7395 100644 --- a/snark-verifier/examples/evm-verifier-with-accumulator.rs +++ b/snark-verifier/examples/evm-verifier-with-accumulator.rs @@ -501,7 +501,7 @@ fn gen_aggregation_evm_verifier( let proof = PlonkVerifier::read_proof(&vk, &protocol, &instances, &mut transcript).unwrap(); PlonkVerifier::verify(&vk, &protocol, &instances, &proof).unwrap(); - evm::compile_yul(&loader.yul_code()) + evm::compile_solidity(&loader.solidity_code()) } fn evm_verify(deployment_code: Vec, instances: Vec>, proof: Vec) { diff --git a/snark-verifier/examples/evm-verifier.rs b/snark-verifier/examples/evm-verifier.rs index c7f206b1..d541528a 100644 --- a/snark-verifier/examples/evm-verifier.rs +++ b/snark-verifier/examples/evm-verifier.rs @@ -237,7 +237,7 @@ fn gen_evm_verifier( let proof = PlonkVerifier::read_proof(&vk, &protocol, &instances, &mut transcript).unwrap(); PlonkVerifier::verify(&vk, &protocol, &instances, &proof).unwrap(); - evm::compile_yul(&loader.yul_code()) + evm::compile_solidity(&loader.solidity_code()) } fn evm_verify(deployment_code: Vec, instances: Vec>, proof: Vec) { diff --git a/snark-verifier/src/loader/evm.rs b/snark-verifier/src/loader/evm.rs index 74ed0f4e..19b145bb 100644 --- a/snark-verifier/src/loader/evm.rs +++ b/snark-verifier/src/loader/evm.rs @@ -6,6 +6,6 @@ pub(crate) mod util; pub use loader::{EcPoint, EvmLoader, Scalar}; pub use util::{ - compile_yul, deploy_and_call, encode_calldata, estimate_gas, fe_to_u256, modulus, u256_to_fe, - Address, B256, U256, U512, + compile_solidity, deploy_and_call, encode_calldata, estimate_gas, fe_to_u256, modulus, + u256_to_fe, Address, B256, U256, U512, }; diff --git a/snark-verifier/src/loader/evm/code.rs b/snark-verifier/src/loader/evm/code.rs index 236684d6..2634ba2d 100644 --- a/snark-verifier/src/loader/evm/code.rs +++ b/snark-verifier/src/loader/evm/code.rs @@ -6,55 +6,49 @@ pub enum Precompiled { } #[derive(Clone, Debug)] -pub struct YulCode { +pub struct SolidityAssemblyCode { // runtime code area runtime: String, } -impl YulCode { +impl SolidityAssemblyCode { pub fn new() -> Self { - YulCode { runtime: String::new() } + Self { runtime: String::new() } } pub fn code(&self, base_modulus: String, scalar_modulus: String) -> String { format!( " - object \"plonk_verifier\" {{ - code {{ - function allocate(size) -> ptr {{ - ptr := mload(0x40) - if eq(ptr, 0) {{ ptr := 0x60 }} - mstore(0x40, add(ptr, size)) +// SPDX-License-Identifier: MIT + +pragma solidity 0.8.19; + +contract Halo2Verifier {{ + fallback(bytes calldata) external returns (bytes memory) {{ + assembly {{ + let success := true + let f_p := {base_modulus} + let f_q := {scalar_modulus} + function validate_ec_point(x, y) -> valid {{ + {{ + let x_lt_p := lt(x, {base_modulus}) + let y_lt_p := lt(y, {base_modulus}) + valid := and(x_lt_p, y_lt_p) }} - let size := datasize(\"Runtime\") - let offset := allocate(size) - datacopy(offset, dataoffset(\"Runtime\"), size) - return(offset, size) - }} - object \"Runtime\" {{ - code {{ - let success:bool := true - let f_p := {base_modulus} - let f_q := {scalar_modulus} - function validate_ec_point(x, y) -> valid:bool {{ - {{ - let x_lt_p:bool := lt(x, {base_modulus}) - let y_lt_p:bool := lt(y, {base_modulus}) - valid := and(x_lt_p, y_lt_p) - }} - {{ - let y_square := mulmod(y, y, {base_modulus}) - let x_square := mulmod(x, x, {base_modulus}) - let x_cube := mulmod(x_square, x, {base_modulus}) - let x_cube_plus_3 := addmod(x_cube, 3, {base_modulus}) - let is_affine:bool := eq(x_cube_plus_3, y_square) - valid := and(valid, is_affine) - }} - }} - {} + {{ + let y_square := mulmod(y, y, {base_modulus}) + let x_square := mulmod(x, x, {base_modulus}) + let x_cube := mulmod(x_square, x, {base_modulus}) + let x_cube_plus_3 := addmod(x_cube, 3, {base_modulus}) + let is_affine := eq(x_cube_plus_3, y_square) + valid := and(valid, is_affine) }} }} - }}", + {} + }} + }} +}} + ", self.runtime ) } diff --git a/snark-verifier/src/loader/evm/loader.rs b/snark-verifier/src/loader/evm/loader.rs index 127cc7e4..3bf49baf 100644 --- a/snark-verifier/src/loader/evm/loader.rs +++ b/snark-verifier/src/loader/evm/loader.rs @@ -1,7 +1,7 @@ use crate::{ loader::{ evm::{ - code::{Precompiled, YulCode}, + code::{Precompiled, SolidityAssemblyCode}, fe_to_u256, modulus, u256_to_fe, U256, U512, }, EcPointLoader, LoadedEcPoint, LoadedScalar, Loader, ScalarLoader, @@ -52,7 +52,7 @@ impl Value { pub struct EvmLoader { base_modulus: U256, scalar_modulus: U256, - code: RefCell, + code: RefCell, ptr: RefCell, cache: RefCell>, } @@ -70,7 +70,7 @@ impl EvmLoader { { let base_modulus = modulus::(); let scalar_modulus = modulus::(); - let code = YulCode::new(); + let code = SolidityAssemblyCode::new(); Rc::new(Self { base_modulus, @@ -81,10 +81,14 @@ impl EvmLoader { }) } - /// Returns generated yul code. - pub fn yul_code(self: &Rc) -> String { + /// Returns generated Solidity code. This is "Solidity" code that is wrapped in an assembly block. + /// In other words, it's basically just assembly (equivalently, Yul). + pub fn solidity_code(self: &Rc) -> String { let code = " - if not(success) { revert(0, 0) } + // Revert if anything fails + if iszero(success) { revert(0, 0) } + + // Return empty bytes on success return(0, 0)" .to_string(); self.code.borrow_mut().runtime_append(code); @@ -104,7 +108,7 @@ impl EvmLoader { *self.ptr.borrow() } - pub(crate) fn code_mut(&self) -> impl DerefMut + '_ { + pub(crate) fn code_mut(&self) -> impl DerefMut + '_ { self.code.borrow_mut() } diff --git a/snark-verifier/src/loader/evm/util.rs b/snark-verifier/src/loader/evm/util.rs index 747849d4..031e85b9 100644 --- a/snark-verifier/src/loader/evm/util.rs +++ b/snark-verifier/src/loader/evm/util.rs @@ -101,13 +101,12 @@ pub fn estimate_gas(cost: Cost) -> usize { intrinsic_cost + calldata_cost + ec_operation_cost } -/// Compile given yul `code` into deployment bytecode. -pub fn compile_yul(code: &str) -> Vec { +/// Compile given Solidity `code` into deployment bytecode. +pub fn compile_solidity(code: &str) -> Vec { let mut cmd = Command::new("solc") .stdin(Stdio::piped()) .stdout(Stdio::piped()) .arg("--bin") - .arg("--yul") .arg("-") .spawn() .unwrap(); From eacd54bb2aab3f18777d263a2ea41702eccdbba7 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Mon, 11 Sep 2023 01:08:45 -0700 Subject: [PATCH 16/19] chore: try pragma solidity 0.8.20 with CI --- snark-verifier/src/loader/evm/code.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/snark-verifier/src/loader/evm/code.rs b/snark-verifier/src/loader/evm/code.rs index 2634ba2d..193b66e9 100644 --- a/snark-verifier/src/loader/evm/code.rs +++ b/snark-verifier/src/loader/evm/code.rs @@ -21,7 +21,7 @@ impl SolidityAssemblyCode { " // SPDX-License-Identifier: MIT -pragma solidity 0.8.19; +pragma solidity >=0.8.19 <0.8.21; contract Halo2Verifier {{ fallback(bytes calldata) external returns (bytes memory) {{ From 8776fbde6098a474a1c4c5a1347da58ae623d0e3 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Tue, 19 Sep 2023 14:11:59 -0700 Subject: [PATCH 17/19] chore: make `transcript_initial_state` public So we can read transcript initial state from `VerifyingKey` --- snark-verifier/src/system/halo2.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/snark-verifier/src/system/halo2.rs b/snark-verifier/src/system/halo2.rs index 74824361..d62ab26f 100644 --- a/snark-verifier/src/system/halo2.rs +++ b/snark-verifier/src/system/halo2.rs @@ -716,7 +716,9 @@ impl Transcript for MockTranscript } } -fn transcript_initial_state(vk: &VerifyingKey) -> C::Scalar { +/// Returns the transcript initial state of the [VerifyingKey]. +/// Roundabout way to do it because [VerifyingKey] doesn't expose the field. +pub fn transcript_initial_state(vk: &VerifyingKey) -> C::Scalar { let mut transcript = MockTranscript::default(); vk.hash_into(&mut transcript).unwrap(); transcript.0 From 14471ed12516c495e9268d8932a31d06902adc9e Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Tue, 19 Sep 2023 22:28:05 -0700 Subject: [PATCH 18/19] test: edit range_check example to trigger selector compression --- snark-verifier-sdk/examples/range_check.rs | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/snark-verifier-sdk/examples/range_check.rs b/snark-verifier-sdk/examples/range_check.rs index 2beb5a78..3d75c2cd 100644 --- a/snark-verifier-sdk/examples/range_check.rs +++ b/snark-verifier-sdk/examples/range_check.rs @@ -14,7 +14,7 @@ use snark_verifier_sdk::{ Snark, }; -fn generate_circuit(k: u32) -> Snark { +fn generate_circuit(k: u32, fill: bool) -> Snark { let lookup_bits = k as usize - 1; let circuit_params = BaseCircuitParams { k: k as usize, @@ -30,20 +30,31 @@ fn generate_circuit(k: u32) -> Snark { let ctx = builder.main(0); let x = ctx.load_witness(Fr::from(14)); - range.range_check(ctx, x, 2 * lookup_bits + 1); - range.gate().add(ctx, x, x); + if fill { + for _ in 0..2 << k { + range.gate().add(ctx, x, x); + } + } let params = gen_srs(k); // do not call calculate_params, we want to use fixed params let pk = gen_pk(¶ms, &builder, None); + // std::fs::remove_file(Path::new("examples/app.pk")).ok(); + // let _pk = gen_pk(¶ms, &builder, Some(Path::new("examples/app.pk"))); + // let pk = read_pk::>( + // Path::new("examples/app.pk"), + // builder.config_params.clone(), + // ) + // .unwrap(); + // std::fs::remove_file(Path::new("examples/app.pk")).ok(); // builder now has break_point set gen_snark_shplonk(¶ms, &pk, builder, None::<&str>) } fn main() { - let dummy_snark = generate_circuit(9); + let dummy_snark = generate_circuit(9, false); - let k = 14u32; + let k = 16u32; let lookup_bits = k as usize - 1; let params = gen_srs(k); let mut agg_circuit = AggregationCircuit::new::( @@ -57,10 +68,14 @@ fn main() { let start0 = start_timer!(|| "gen vk & pk"); let pk = gen_pk(¶ms, &agg_circuit, None); + // std::fs::remove_file(Path::new("examples/agg.pk")).ok(); + // let _pk = gen_pk(¶ms, &agg_circuit, Some(Path::new("examples/agg.pk"))); end_timer!(start0); + // let pk = read_pk::(Path::new("examples/agg.pk"), agg_config).unwrap(); + // std::fs::remove_file(Path::new("examples/agg.pk")).ok(); let break_points = agg_circuit.break_points(); - let snarks = (10..16).map(generate_circuit).collect_vec(); + let snarks = (10..16).map(|k| generate_circuit(k, true)).collect_vec(); for (i, snark) in snarks.into_iter().enumerate() { let agg_circuit = AggregationCircuit::new::( CircuitBuilderStage::Prover, From 223fbd722a3bedeaa23056f1313b4332f3db17e3 Mon Sep 17 00:00:00 2001 From: Jonathan Wang <31040440+jonathanpwang@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:52:03 -0700 Subject: [PATCH 19/19] [feat] add `aggregate_snarks` function (#34) * feat: add `aggregate_snarks` function - Previously you could only create a new `builder` pre-populated with the witnesses for snark aggregation. - This is a bad design pattern if you want to make a circuit that aggregates and also does other stuff. - This function will use whatever `SinglePhaseCoreManager` and `RangeChip` you provide to prove the snark aggregation. * chore: add comment * chore: fix comment --- snark-verifier-sdk/src/halo2/aggregation.rs | 184 ++++++++++++-------- 1 file changed, 114 insertions(+), 70 deletions(-) diff --git a/snark-verifier-sdk/src/halo2/aggregation.rs b/snark-verifier-sdk/src/halo2/aggregation.rs index 690a64fc..9488e2a9 100644 --- a/snark-verifier-sdk/src/halo2/aggregation.rs +++ b/snark-verifier-sdk/src/halo2/aggregation.rs @@ -6,7 +6,8 @@ use halo2_base::{ circuit::{ builder::BaseCircuitBuilder, BaseCircuitParams, BaseConfig, CircuitBuilderStage, }, - flex_gate::MultiPhaseThreadBreakPoints, + flex_gate::{threads::SinglePhaseCoreManager, MultiPhaseThreadBreakPoints}, + RangeChip, }, halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner}, @@ -314,6 +315,116 @@ pub trait Halo2KzgAccumulationScheme<'a> = PolynomialCommitmentScheme< VerifyingKey = KzgAsVerifyingKey, > + AccumulationSchemeProver>; +/// **Private** witnesses that form the output of [aggregate_snarks]. +/// Same as [SnarkAggregationWitness] except that we flatten `accumulator` into a vector of field elements. +#[derive(Clone, Debug)] +pub struct SnarkAggregationOutput { + pub previous_instances: Vec>>, + pub accumulator: Vec>, + /// This returns the assigned `preprocessed` and `transcript_initial_state` values as a vector of assigned values, one for each aggregated snark. + /// These can then be exposed as public instances. + pub preprocessed: Vec, +} + +/// Given snarks, this populates the circuit builder with the virtual cells and constraints necessary to verify all the snarks. +/// +/// ## Notes +/// - This function does _not_ expose any public instances. +/// - `svk` is the generator of the KZG trusted setup, usually gotten via `params.get_g()[0]` +/// (avoids having to pass `params` into function just to get generator) +/// +/// ## Universality +/// - If `universality` is not `None`, then the verifying keys of each snark in `snarks` is loaded as a witness in the circuit. +/// - Moreover, if `universality` is `Full`, then the number of rows `n` of each snark in `snarks` is also loaded as a witness. In this case the generator `omega` of the order `n` multiplicative subgroup of `F` is also loaded as a witness. +/// - By default, these witnesses are _private_ and returned in `self.preprocessed_digests +/// - The user can optionally modify the circuit after calling this function to add more instances to `assigned_instances` to expose. +/// +/// ## Warning +/// Will fail silently if `snarks` were created using a different multi-open scheme than `AS` +/// where `AS` can be either [`crate::SHPLONK`] or [`crate::GWC`] (for original PLONK multi-open scheme) +/// +/// ## Assumptions +/// - `pool` and `range` reference the same `SharedCopyConstraintManager`. +pub fn aggregate_snarks( + pool: &mut SinglePhaseCoreManager, + range: &RangeChip, + svk: Svk, // gotten by params.get_g()[0].into() + snarks: impl IntoIterator, + universality: VerifierUniversality, +) -> SnarkAggregationOutput +where + AS: for<'a> Halo2KzgAccumulationScheme<'a>, +{ + let snarks = snarks.into_iter().collect_vec(); + + let mut transcript_read = + PoseidonTranscript::::from_spec(&[], POSEIDON_SPEC.clone()); + // TODO: the snarks can probably store these accumulators + let accumulators = snarks + .iter() + .flat_map(|snark| { + transcript_read.new_stream(snark.proof()); + let proof = PlonkSuccinctVerifier::::read_proof( + &svk, + &snark.protocol, + &snark.instances, + &mut transcript_read, + ) + .unwrap(); + PlonkSuccinctVerifier::::verify(&svk, &snark.protocol, &snark.instances, &proof) + .unwrap() + }) + .collect_vec(); + + let (_accumulator, as_proof) = { + let mut transcript_write = + PoseidonTranscript::>::from_spec(vec![], POSEIDON_SPEC.clone()); + let rng = StdRng::from_entropy(); + let accumulator = + AS::create_proof(&Default::default(), &accumulators, &mut transcript_write, rng) + .unwrap(); + (accumulator, transcript_write.finalize()) + }; + + // create halo2loader + let fp_chip = FpChip::::new(range, BITS, LIMBS); + let ecc_chip = BaseFieldEccChip::new(&fp_chip); + // `pool` needs to be owned by loader. + // We put it back later (below), so it should have same effect as just mutating `pool`. + let tmp_pool = mem::take(pool); + // range_chip has shared reference to LookupAnyManager, with shared CopyConstraintManager + // pool has shared reference to CopyConstraintManager + let loader = Halo2Loader::new(ecc_chip, tmp_pool); + + // run witness and copy constraint generation + let SnarkAggregationWitness { previous_instances, accumulator, preprocessed } = + aggregate::(&svk, &loader, &snarks, as_proof.as_slice(), universality); + let lhs = accumulator.lhs.assigned(); + let rhs = accumulator.rhs.assigned(); + let accumulator = lhs + .x() + .limbs() + .iter() + .chain(lhs.y().limbs().iter()) + .chain(rhs.x().limbs().iter()) + .chain(rhs.y().limbs().iter()) + .copied() + .collect_vec(); + + #[cfg(debug_assertions)] + { + let KzgAccumulator { lhs, rhs } = _accumulator; + let instances = + [lhs.x, lhs.y, rhs.x, rhs.y].map(fe_to_limbs::<_, Fr, LIMBS, BITS>).concat(); + for (lhs, rhs) in instances.iter().zip(accumulator.iter()) { + assert_eq!(lhs, rhs.value()); + } + } + // put back `pool` into `builder` + *pool = loader.take_ctx(); + SnarkAggregationOutput { previous_instances, accumulator, preprocessed } +} + impl AggregationCircuit { /// Given snarks, this creates `BaseCircuitBuilder` and populates the circuit builder with the virtual cells and constraints necessary to verify all the snarks. /// @@ -339,77 +450,10 @@ impl AggregationCircuit { AS: for<'a> Halo2KzgAccumulationScheme<'a>, { let svk: Svk = params.get_g()[0].into(); - let snarks = snarks.into_iter().collect_vec(); - - let mut transcript_read = - PoseidonTranscript::::from_spec(&[], POSEIDON_SPEC.clone()); - // TODO: the snarks can probably store these accumulators - let accumulators = snarks - .iter() - .flat_map(|snark| { - transcript_read.new_stream(snark.proof()); - let proof = PlonkSuccinctVerifier::::read_proof( - &svk, - &snark.protocol, - &snark.instances, - &mut transcript_read, - ) - .unwrap(); - PlonkSuccinctVerifier::::verify(&svk, &snark.protocol, &snark.instances, &proof) - .unwrap() - }) - .collect_vec(); - - let (_accumulator, as_proof) = { - let mut transcript_write = PoseidonTranscript::>::from_spec( - vec![], - POSEIDON_SPEC.clone(), - ); - let rng = StdRng::from_entropy(); - let accumulator = - AS::create_proof(&Default::default(), &accumulators, &mut transcript_write, rng) - .unwrap(); - (accumulator, transcript_write.finalize()) - }; - let mut builder = BaseCircuitBuilder::from_stage(stage).use_params(config_params.into()); - // create halo2loader let range = builder.range_chip(); - let fp_chip = FpChip::::new(&range, BITS, LIMBS); - let ecc_chip = BaseFieldEccChip::new(&fp_chip); - // Take the phase 0 pool from `builder`; it needs to be owned by loader. - // We put it back later (below), so it should have same effect as just mutating `builder.pool(0)`. - let pool = mem::take(builder.pool(0)); - // range_chip has shared reference to LookupAnyManager, with shared CopyConstraintManager - // pool has shared reference to CopyConstraintManager - let loader = Halo2Loader::new(ecc_chip, pool); - - // run witness and copy constraint generation - let SnarkAggregationWitness { previous_instances, accumulator, preprocessed } = - aggregate::(&svk, &loader, &snarks, as_proof.as_slice(), universality); - let lhs = accumulator.lhs.assigned(); - let rhs = accumulator.rhs.assigned(); - let accumulator = lhs - .x() - .limbs() - .iter() - .chain(lhs.y().limbs().iter()) - .chain(rhs.x().limbs().iter()) - .chain(rhs.y().limbs().iter()) - .copied() - .collect_vec(); - - #[cfg(debug_assertions)] - { - let KzgAccumulator { lhs, rhs } = _accumulator; - let instances = - [lhs.x, lhs.y, rhs.x, rhs.y].map(fe_to_limbs::<_, Fr, LIMBS, BITS>).concat(); - for (lhs, rhs) in instances.iter().zip(accumulator.iter()) { - assert_eq!(lhs, rhs.value()); - } - } - // put back `pool` into `builder` - *builder.pool(0) = loader.take_ctx(); + let SnarkAggregationOutput { previous_instances, accumulator, preprocessed } = + aggregate_snarks::(builder.pool(0), &range, svk, snarks, universality); assert_eq!( builder.assigned_instances.len(), 1,