From 86f8cbd886b5193f869dec9cb7783ede4d3750da Mon Sep 17 00:00:00 2001 From: Alex Kuzmin Date: Tue, 16 Apr 2024 16:13:26 +0800 Subject: [PATCH] Implement PoC hyperplonk circuit --- .github/workflows/rust.yml | 22 +- backend/Cargo.lock | 131 +- backend/Cargo.toml | 4 +- prover/.gitignore | 20 +- prover/Cargo.lock | 4283 +++-------------- prover/Cargo.toml | 41 +- prover/README.md | 99 +- prover/benches/kzg.rs | 306 -- prover/benches/proof_of_liabilities.rs | 87 + prover/bin/commitment_solidity_calldata.json | 8 - prover/bin/gen_commit_and_proofs.rs | 246 - prover/bin/gen_verifier.rs | 147 - .../inclusion_proof_solidity_calldata.json | 15 - .../examples/chunked_univariate_grand_sum.rs | 178 - prover/prints/range-check-layout.png | Bin 80109 -> 77731 bytes ...layout.png => summa-hyperplonk-layout.png} | Bin 1087709 -> 1082947 bytes prover/rust-toolchain | 1 - prover/src/chips/range/range_check.rs | 4 +- prover/src/chips/range/tests.rs | 14 +- prover/src/circuits/mod.rs | 4 +- prover/src/circuits/summa_circuit.rs | 274 ++ prover/src/circuits/tests.rs | 651 +-- prover/src/circuits/univariate_grand_sum.rs | 325 -- prover/src/circuits/utils.rs | 561 --- prover/src/lib.rs | 9 +- prover/src/utils/amortized_kzg.rs | 154 - prover/src/utils/csv_parser.rs | 74 - prover/src/utils/mod.rs | 3 - 28 files changed, 1207 insertions(+), 6454 deletions(-) delete mode 100644 prover/benches/kzg.rs create mode 100644 prover/benches/proof_of_liabilities.rs delete mode 100644 prover/bin/commitment_solidity_calldata.json delete mode 100644 prover/bin/gen_commit_and_proofs.rs delete mode 100644 prover/bin/gen_verifier.rs delete mode 100644 prover/bin/inclusion_proof_solidity_calldata.json delete mode 100644 prover/examples/chunked_univariate_grand_sum.rs rename prover/prints/{univariate-grand-sum-layout.png => summa-hyperplonk-layout.png} (96%) delete mode 100644 prover/rust-toolchain create mode 100644 prover/src/circuits/summa_circuit.rs delete mode 100644 prover/src/circuits/univariate_grand_sum.rs delete mode 100644 prover/src/circuits/utils.rs delete mode 100644 prover/src/utils/amortized_kzg.rs delete mode 100644 prover/src/utils/csv_parser.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4dd38496..1ba15d57 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -31,7 +31,7 @@ jobs: aws-region: us-west-2 - name: Wakeup runner - run: .github/scripts/wakeup.sh + run: .github/scripts/wakeup.sh build: runs-on: [summa-solvency-runner] @@ -46,7 +46,7 @@ jobs: - name: Install solc run: (hash svm 2>/dev/null || cargo install --version 0.2.23 svm-rs) && svm install 0.8.20 && solc --version - - name: Test KZG Prover + - name: Test Prover run: | cd prover cargo test --release -- --nocapture @@ -54,13 +54,13 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 - - name: Test backend - run: | - cd backend - cargo test --release -- --nocapture + # TODO restore workflow + # - name: Test backend + # run: | + # cd backend + # cargo test --release -- --nocapture - - name: Test example - run: | - cd backend - cargo run --release --example summa_solvency_flow - + # - name: Test example + # run: | + # cd backend + # cargo run --release --example summa_solvency_flow diff --git a/backend/Cargo.lock b/backend/Cargo.lock index 08359b39..f6a50e97 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -66,11 +66,10 @@ checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" [[package]] name = "ark-std" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" +checksum = "94893f1e0c6eeab764ade8dc4c0db24caf4fe7cbbaafc0eba0a9030f447b5185" dependencies = [ - "colored", "num-traits", "rand", ] @@ -481,17 +480,6 @@ dependencies = [ "thiserror", ] -[[package]] -name = "colored" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" -dependencies = [ - "is-terminal", - "lazy_static", - "windows-sys", -] - [[package]] name = "const-oid" version = "0.9.4" @@ -1336,6 +1324,7 @@ version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ + "serde", "typenum", "version_check", "zeroize", @@ -1408,6 +1397,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "halo2_proofs" +version = "0.2.0" +source = "git+https://github.com/han0110/halo2.git?branch=feature/for-benchmark#4981b8d5bdaab04af9b56a5d2c482b6eec9f7fa4" +dependencies = [ + "ark-std", + "blake2b_simd", + "ff", + "group", + "halo2curves 0.3.3", + "rand_chacha", + "rand_core", + "rayon", + "sha3 0.9.1", + "tracing", +] + [[package]] name = "halo2_proofs" version = "0.2.0" @@ -1416,7 +1422,7 @@ dependencies = [ "blake2b_simd", "ff", "group", - "halo2curves", + "halo2curves 0.1.0", "maybe-rayon", "rand_chacha", "rand_core", @@ -1431,7 +1437,7 @@ source = "git+https://github.com/summa-dev/halo2-solidity-verifier#d33972567f83f dependencies = [ "askama", "blake2b_simd", - "halo2_proofs", + "halo2_proofs 0.2.0 (git+https://github.com/summa-dev/halo2)", "hex", "itertools 0.11.0", "revm", @@ -1459,6 +1465,43 @@ dependencies = [ "subtle", ] +[[package]] +name = "halo2curves" +version = "0.3.2" +source = "git+https://github.com/privacy-scaling-explorations/halo2curves.git?tag=0.3.2#9f5c50810bbefe779ee5cf1d852b2fe85dc35d5e" +dependencies = [ + "ff", + "group", + "lazy_static", + "num-bigint", + "num-traits", + "pasta_curves", + "paste", + "rand", + "rand_core", + "static_assertions", + "subtle", +] + +[[package]] +name = "halo2curves" +version = "0.3.3" +source = "git+https://github.com/privacy-scaling-explorations/halo2curves?tag=0.3.3#8e4cb9f0c66c864e8ca25da07f50ae95f664a5b7" +dependencies = [ + "ff", + "group", + "lazy_static", + "num-bigint", + "num-traits", + "pasta_curves", + "paste", + "rand", + "rand_core", + "serde", + "static_assertions", + "subtle", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1506,6 +1549,9 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] [[package]] name = "hex-literal" @@ -2214,8 +2260,10 @@ dependencies = [ "blake2b_simd", "ff", "group", + "hex", "lazy_static", "rand", + "serde", "static_assertions", "subtle", ] @@ -2376,6 +2424,36 @@ version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" +[[package]] +name = "plonkish_backend" +version = "0.1.0" +source = "git+https://github.com/han0110/plonkish#303cf244803ea56d1ac8c24829ec4c67e4e798ab" +dependencies = [ + "bincode", + "bitvec 1.0.1", + "generic-array", + "halo2_proofs 0.2.0 (git+https://github.com/han0110/halo2.git?branch=feature/for-benchmark)", + "halo2curves 0.3.3", + "itertools 0.10.5", + "num-bigint", + "num-integer", + "pasta_curves", + "poseidon", + "rand", + "rayon", + "serde", + "sha3 0.10.8", +] + +[[package]] +name = "poseidon" +version = "0.2.0" +source = "git+https://github.com/han0110/poseidon?branch=feature/with-spec#fa4c2544ed38666f1f72d1c4fd0956756a7112b3" +dependencies = [ + "halo2curves 0.3.2", + "subtle", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -3201,7 +3279,7 @@ dependencies = [ "csv", "ethers", "futures", - "halo2_proofs", + "halo2_proofs 0.2.0 (git+https://github.com/han0110/halo2.git?branch=feature/for-benchmark)", "halo2_solidity_verifier", "num-bigint", "num-traits", @@ -3209,29 +3287,20 @@ dependencies = [ "reqwest", "serde", "serde_json", - "summa-solvency", + "summa-hyperplonk", "tokio", ] [[package]] -name = "summa-solvency" -version = "0.2.0" +name = "summa-hyperplonk" +version = "0.3.0" dependencies = [ - "ark-std", "csv", - "ethers", - "halo2_proofs", - "halo2_solidity_verifier", - "hex", - "itertools 0.10.5", + "halo2_proofs 0.2.0 (git+https://github.com/han0110/halo2.git?branch=feature/for-benchmark)", "num-bigint", - "num-traits", - "num_cpus", + "plonkish_backend", "rand", "rayon", - "regex", - "serde", - "serde_json", ] [[package]] diff --git a/backend/Cargo.toml b/backend/Cargo.toml index b6b902e0..41afc304 100644 --- a/backend/Cargo.toml +++ b/backend/Cargo.toml @@ -6,8 +6,8 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -summa-solvency = { path = "../prover" } -halo2_proofs = { git = "https://github.com/summa-dev/halo2"} +summa-hyperplonk = { path = "../prover" } +halo2_proofs = { git = "https://github.com/han0110/halo2.git", branch = "feature/for-benchmark", optional = true } csv = "1.2.2" futures = "0.3.28" num-bigint = "0.4.3" diff --git a/prover/.gitignore b/prover/.gitignore index d7c172bc..074070ee 100644 --- a/prover/.gitignore +++ b/prover/.gitignore @@ -1,5 +1,21 @@ # Generated by Cargo # will have compiled files and executables +debug/ +target/ + +# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries +# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html +Cargo.lock + +# These are backup files generated by rustfmt +**/*.rs.bk + +# MSVC Windows builds of rustc generate these, which store debugging information +*.pdb + +# Added by cargo + /target -/ptau -/benches/csv + +#VSCode +.vscode/ diff --git a/prover/Cargo.lock b/prover/Cargo.lock index 84c8d67a..97fe6344 100644 --- a/prover/Cargo.lock +++ b/prover/Cargo.lock @@ -2,108 +2,21 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -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.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "ahash" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" -dependencies = [ - "cfg-if", - "once_cell", - "version_check", - "zerocopy", -] - [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] -[[package]] -name = "allocator-api2" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" - -[[package]] -name = "alloy-primitives" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0628ec0ba5b98b3370bb6be17b12f23bfce8ee4ad83823325a20546d9b03b78" -dependencies = [ - "alloy-rlp", - "bytes", - "cfg-if", - "const-hex", - "derive_more", - "hex-literal", - "itoa", - "ruint", - "tiny-keccak", -] - -[[package]] -name = "alloy-rlp" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" -dependencies = [ - "alloy-rlp-derive", - "arrayvec", - "bytes", -] - -[[package]] -name = "alloy-rlp-derive" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - [[package]] name = "android-tzdata" version = "0.1.1" @@ -121,124 +34,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" - -[[package]] -name = "ark-ff" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b3235cc41ee7a12aaaf2c575a2ad7b46713a8a50bda2fc3b003a04845c05dd6" -dependencies = [ - "ark-ff-asm 0.3.0", - "ark-ff-macros 0.3.0", - "ark-serialize 0.3.0", - "ark-std 0.3.0", - "derivative", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.3.3", - "zeroize", -] - -[[package]] -name = "ark-ff" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec847af850f44ad29048935519032c33da8aa03340876d351dfab5660d2966ba" -dependencies = [ - "ark-ff-asm 0.4.2", - "ark-ff-macros 0.4.2", - "ark-serialize 0.4.2", - "ark-std 0.4.0", - "derivative", - "digest 0.10.7", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "paste", - "rustc_version 0.4.0", - "zeroize", -] - -[[package]] -name = "ark-ff-asm" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db02d390bf6643fb404d3d22d31aee1c4bc4459600aef9113833d17e786c6e44" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-asm" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed4aa4fe255d0bc6d79373f7e31d2ea147bcf486cba1be5ba7ea85abdb92348" -dependencies = [ - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fd794a08ccb318058009eefdf15bcaaaaf6f8161eb3345f907222bac38b20" -dependencies = [ - "num-bigint", - "num-traits", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-ff-macros" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abe79b0e4288889c4574159ab790824d0033b9fdcb2a112a3182fac2e514565" -dependencies = [ - "num-bigint", - "num-traits", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "ark-serialize" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d6c2b318ee6e10f8c2853e73a83adc0ccb88995aa978d8a3408d492ab2ee671" -dependencies = [ - "ark-std 0.3.0", - "digest 0.9.0", -] - -[[package]] -name = "ark-serialize" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb7b85a02b83d2f22f89bd5cac66c9c89474240cb6207cb1efc16d098e822a5" -dependencies = [ - "ark-std 0.4.0", - "digest 0.10.7", - "num-bigint", -] - -[[package]] -name = "ark-std" -version = "0.3.0" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df2c09229cbc5a028b1d70e00fdb2acee28b1055dfb5ca73eea49c5a25c4e7c" -dependencies = [ - "colored", - "num-traits", - "rand", -] +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "ark-std" @@ -262,199 +60,32 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" -[[package]] -name = "ascii-canvas" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" -dependencies = [ - "term", -] - -[[package]] -name = "askama" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b79091df18a97caea757e28cd2d5fda49c6cd4bd01ddffd7ff01ace0c0ad2c28" -dependencies = [ - "askama_derive", - "askama_escape", -] - -[[package]] -name = "askama_derive" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a0fc7dcf8bd4ead96b1d36b41df47c14beedf7b0301fc543d8f2384e66a2ec0" -dependencies = [ - "askama_parser", - "basic-toml", - "mime", - "mime_guess", - "proc-macro2", - "quote", - "serde", - "syn 2.0.39", -] - -[[package]] -name = "askama_escape" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" - -[[package]] -name = "askama_parser" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c268a96e01a4c47c8c5c2472aaa570707e006a875ea63e819f75474ceedaf7b4" -dependencies = [ - "nom", -] - -[[package]] -name = "async-trait" -version = "0.1.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "async_io_stream" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" -dependencies = [ - "futures", - "pharos", - "rustc_version 0.4.0", -] - [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.19", + "hermit-abi", "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.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" - -[[package]] -name = "base64ct" -version = "1.6.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] -name = "basic-toml" -version = "0.1.7" +name = "bincode" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f2139706359229bfa8f19142ac1155b4b80beafb7a60471ac5dd109d4a19778" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" dependencies = [ "serde", ] -[[package]] -name = "bech32" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" - -[[package]] -name = "bindgen" -version = "0.66.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b84e06fc203107bfbad243f4aba2af864eb7db3b1cf46ea0a023b0b433d2a7" -dependencies = [ - "bitflags 2.4.1", - "cexpr", - "clang-sys", - "lazy_static", - "lazycell", - "log", - "peeking_take_while", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "syn 2.0.39", - "which", -] - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - [[package]] name = "bitflags" version = "1.3.2" @@ -463,9 +94,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "bitvec" @@ -516,170 +147,53 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" [[package]] -name = "blst" -version = "0.3.11" +name = "bumpalo" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" -dependencies = [ - "cc", - "glob", - "threadpool", - "zeroize", -] +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] -name = "bs58" -version = "0.5.0" +name = "bytemuck" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" -dependencies = [ - "sha2", - "tinyvec", -] +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" [[package]] -name = "bumpalo" -version = "3.14.0" +name = "byteorder" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "byte-slice-cast" -version = "1.2.2" +name = "cast" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ac9f8b63eca6fd385229b3675f6cc0dc5c8a5c8a54a59d4f52ffd670d87b0c" +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] -name = "bytemuck" -version = "1.14.0" +name = "cc" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "17f6e324229dc011159fcc089755d1e2e216a90d43a7dea6853ca740b84f35e7" [[package]] -name = "byteorder" -version = "1.5.0" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] -name = "bytes" -version = "1.5.0" +name = "chrono" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" -dependencies = [ - "serde", -] - -[[package]] -name = "c-kzg" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac926d808fb72fe09ebf471a091d6d72918876ccf0b4989766093d2d0d24a0ef" -dependencies = [ - "bindgen", - "blst", - "cc", - "glob", - "hex", - "libc", - "serde", -] - -[[package]] -name = "camino" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e34637b3140142bdf929fb439e8aa4ebad7651ebf7b1080b3930aa16ac1459ff" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" -dependencies = [ - "camino", - "cargo-platform", - "semver 1.0.20", - "serde", - "serde_json", - "thiserror", -] - -[[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.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom", -] - -[[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.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.48.5", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common", - "inout", -] - -[[package]] -name = "clang-sys" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" -dependencies = [ - "glob", - "libc", - "libloading", + "windows-targets", ] [[package]] @@ -693,126 +207,29 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - -[[package]] -name = "coins-bip32" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b6be4a5df2098cd811f3194f64ddb96c267606bffd9689ac7b0160097b01ad3" -dependencies = [ - "bs58", - "coins-core", - "digest 0.10.7", - "hmac", - "k256", - "serde", - "sha2", - "thiserror", -] - -[[package]] -name = "coins-bip39" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db8fba409ce3dc04f7d804074039eb68b960b0829161f8e06c95fea3f122528" -dependencies = [ - "bitvec", - "coins-bip32", - "hmac", - "once_cell", - "pbkdf2 0.12.2", - "rand", - "sha2", - "thiserror", -] - -[[package]] -name = "coins-core" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5286a0843c21f8367f7be734f89df9b822e0321d8bcce8d6e735aadff7d74979" -dependencies = [ - "base64 0.21.5", - "bech32", - "bs58", - "digest 0.10.7", - "generic-array", - "hex", - "ripemd", - "serde", - "serde_derive", - "sha2", - "sha3 0.10.8", - "thiserror", -] - [[package]] name = "color_quant" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" -[[package]] -name = "colored" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" -dependencies = [ - "is-terminal", - "lazy_static", - "windows-sys 0.48.0", -] - [[package]] name = "const-cstr" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3d0b5ff30645a68f35ece8cea4556ca14ef8a1651455f789a099a0513532a6" -[[package]] -name = "const-hex" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5104de16b218eddf8e34ffe2f86f74bfa4e61e95a1b89732fccf6325efd0557" -dependencies = [ - "cfg-if", - "cpufeatures", - "hex", - "proptest", - "serde", -] - -[[package]] -name = "const-oid" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" - [[package]] name = "constant_time_eq" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -820,9 +237,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core-graphics" @@ -839,9 +256,9 @@ dependencies = [ [[package]] name = "core-graphics-types" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bb142d41022986c1d8ff29103a1411c8a3dfad3552f87a4f8dc50d61d4f4e33" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -862,18 +279,18 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] @@ -889,7 +306,7 @@ dependencies = [ "clap", "criterion-plot", "csv", - "itertools 0.10.5", + "itertools", "lazy_static", "num-traits", "oorandom", @@ -911,59 +328,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" dependencies = [ "cast", - "itertools 0.10.5", + "itertools", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crunchy" -version = "0.2.2" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core", - "subtle", - "zeroize", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-common" @@ -996,15 +387,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - [[package]] name = "darling" version = "0.10.2" @@ -1040,36 +422,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "der" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" -dependencies = [ - "const-oid", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" -dependencies = [ - "powerfmt", -] - -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "derive_builder" version = "0.9.0" @@ -1095,25 +447,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "derive_more" -version = "0.99.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" -dependencies = [ - "convert_case", - "proc-macro2", - "quote", - "rustc_version 0.4.0", - "syn 1.0.109", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - [[package]] name = "digest" version = "0.9.0" @@ -1130,18 +463,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer 0.10.4", - "const-oid", "crypto-common", - "subtle", -] - -[[package]] -name = "dirs" -version = "5.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" -dependencies = [ - "dirs-sys", ] [[package]] @@ -1154,18 +476,6 @@ dependencies = [ "dirs-sys-next", ] -[[package]] -name = "dirs-sys" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.48.0", -] - [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -1186,12 +496,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "dunce" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" - [[package]] name = "dwrote" version = "0.11.0" @@ -1204,512 +508,57 @@ dependencies = [ "wio", ] -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest 0.10.7", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - [[package]] name = "either" -version = "1.9.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] -name = "elliptic-curve" -version = "0.13.8" +name = "fdeflate" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ - "base16ct", - "crypto-bigint", - "digest 0.10.7", - "ff", - "generic-array", - "group", - "pkcs8", - "rand_core", - "sec1", - "subtle", - "zeroize", + "simd-adler32", ] [[package]] -name = "ena" -version = "0.14.2" +name = "ff" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c533630cf40e9caa44bd91aadc88a75d75a4c3a12b4cfde353cbed41daa1e1f1" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" dependencies = [ - "log", + "bitvec", + "rand_core", + "subtle", ] [[package]] -name = "encoding_rs" -version = "0.8.33" +name = "flate2" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" dependencies = [ - "cfg-if", + "crc32fast", + "miniz_oxide", ] [[package]] -name = "enr" -version = "0.9.1" +name = "float-ord" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe81b5c06ecfdbc71dd845216f225f53b62a10cb8a16c946836a3467f701d05b" -dependencies = [ - "base64 0.21.5", - "bytes", - "hex", - "k256", - "log", - "rand", - "rlp", - "serde", - "sha3 0.10.8", - "zeroize", -] +checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" [[package]] -name = "enumn" -version = "0.1.12" +name = "fnv" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] -name = "equivalent" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" - -[[package]] -name = "errno" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "eth-keystore" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fda3bf123be441da5260717e0661c25a2fd9cb2b2c1d20bf2e05580047158ab" -dependencies = [ - "aes", - "ctr", - "digest 0.10.7", - "hex", - "hmac", - "pbkdf2 0.11.0", - "rand", - "scrypt", - "serde", - "serde_json", - "sha2", - "sha3 0.10.8", - "thiserror", - "uuid", -] - -[[package]] -name = "ethabi" -version = "18.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7413c5f74cc903ea37386a8965a936cbeb334bd270862fdece542c1b2dcbc898" -dependencies = [ - "ethereum-types", - "hex", - "once_cell", - "regex", - "serde", - "serde_json", - "sha3 0.10.8", - "thiserror", - "uint", -] - -[[package]] -name = "ethbloom" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c22d4b5885b6aa2fe5e8b9329fb8d232bf739e434e6b87347c63bdd00c120f60" -dependencies = [ - "crunchy", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "tiny-keccak", -] - -[[package]] -name = "ethereum-types" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02d215cbf040552efcbe99a38372fe80ab9d00268e20012b79fcd0f073edd8ee" -dependencies = [ - "ethbloom", - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "primitive-types", - "scale-info", - "uint", -] - -[[package]] -name = "ethers" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5344eea9b20effb5efeaad29418215c4d27017639fd1f908260f59cbbd226e" -dependencies = [ - "ethers-addressbook", - "ethers-contract", - "ethers-core", - "ethers-etherscan", - "ethers-middleware", - "ethers-providers", - "ethers-signers", - "ethers-solc", -] - -[[package]] -name = "ethers-addressbook" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c405f24ea3a517899ba7985385c43dc4a7eb1209af3b1e0a1a32d7dcc7f8d09" -dependencies = [ - "ethers-core", - "once_cell", - "serde", - "serde_json", -] - -[[package]] -name = "ethers-contract" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0111ead599d17a7bff6985fd5756f39ca7033edc79a31b23026a8d5d64fa95cd" -dependencies = [ - "const-hex", - "ethers-contract-abigen", - "ethers-contract-derive", - "ethers-core", - "ethers-providers", - "futures-util", - "once_cell", - "pin-project", - "serde", - "serde_json", - "thiserror", -] - -[[package]] -name = "ethers-contract-abigen" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51258120c6b47ea9d9bec0d90f9e8af71c977fbefbef8213c91bfed385fe45eb" -dependencies = [ - "Inflector", - "const-hex", - "dunce", - "ethers-core", - "eyre", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "serde", - "serde_json", - "syn 2.0.39", - "toml", - "walkdir", -] - -[[package]] -name = "ethers-contract-derive" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "936e7a0f1197cee2b62dc89f63eff3201dbf87c283ff7e18d86d38f83b845483" -dependencies = [ - "Inflector", - "const-hex", - "ethers-contract-abigen", - "ethers-core", - "proc-macro2", - "quote", - "serde_json", - "syn 2.0.39", -] - -[[package]] -name = "ethers-core" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f03e0bdc216eeb9e355b90cf610ef6c5bb8aca631f97b5ae9980ce34ea7878d" -dependencies = [ - "arrayvec", - "bytes", - "cargo_metadata", - "chrono", - "const-hex", - "elliptic-curve", - "ethabi", - "generic-array", - "k256", - "num_enum", - "once_cell", - "open-fastrlp", - "rand", - "rlp", - "serde", - "serde_json", - "strum", - "syn 2.0.39", - "tempfile", - "thiserror", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "ethers-etherscan" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abbac2c890bdbe0f1b8e549a53b00e2c4c1de86bb077c1094d1f38cdf9381a56" -dependencies = [ - "chrono", - "ethers-core", - "ethers-solc", - "reqwest", - "semver 1.0.20", - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "ethers-middleware" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681ece6eb1d10f7cf4f873059a77c04ff1de4f35c63dd7bccde8f438374fcb93" -dependencies = [ - "async-trait", - "auto_impl", - "ethers-contract", - "ethers-core", - "ethers-providers", - "ethers-signers", - "futures-channel", - "futures-locks", - "futures-util", - "instant", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "tracing-futures", - "url", -] - -[[package]] -name = "ethers-providers" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25d6c0c9455d93d4990c06e049abf9b30daf148cf461ee939c11d88907c60816" -dependencies = [ - "async-trait", - "auto_impl", - "base64 0.21.5", - "bytes", - "const-hex", - "enr", - "ethers-core", - "futures-core", - "futures-timer", - "futures-util", - "hashers", - "http", - "instant", - "jsonwebtoken", - "once_cell", - "pin-project", - "reqwest", - "serde", - "serde_json", - "thiserror", - "tokio", - "tracing", - "tracing-futures", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "ws_stream_wasm", -] - -[[package]] -name = "ethers-signers" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cb1b714e227bbd2d8c53528adb580b203009728b17d0d0e4119353aa9bc5532" -dependencies = [ - "async-trait", - "coins-bip32", - "coins-bip39", - "const-hex", - "elliptic-curve", - "eth-keystore", - "ethers-core", - "rand", - "sha2", - "thiserror", - "tracing", -] - -[[package]] -name = "ethers-solc" -version = "2.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a64f710586d147864cff66540a6d64518b9ff37d73ef827fee430538265b595f" -dependencies = [ - "cfg-if", - "const-hex", - "dirs", - "dunce", - "ethers-core", - "glob", - "home", - "md-5", - "num_cpus", - "once_cell", - "path-slash", - "rayon", - "regex", - "semver 1.0.20", - "serde", - "serde_json", - "solang-parser", - "thiserror", - "tiny-keccak", - "tokio", - "tracing", - "walkdir", - "yansi", -] - -[[package]] -name = "eyre" -version = "0.6.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80f656be11ddf91bd709454d15d5bd896fbaf4cc3314e69349e4d1569f5b46cd" -dependencies = [ - "indenter", - "once_cell", -] - -[[package]] -name = "fastrand" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" - -[[package]] -name = "fastrlp" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139834ddba373bbdd213dffe02c8d110508dcf1726c2be27e8d1f7d7e1856418" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", -] - -[[package]] -name = "fdeflate" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64d6dafc854908ff5da46ff3f8f473c6984119a2876a383a860246dd7841a868" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "bitvec", - "rand_core", - "subtle", -] - -[[package]] -name = "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 = "fixedbitset" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" - -[[package]] -name = "flate2" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "float-ord" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bad48618fdb549078c333a7a8528acb57af271d0433bdecd523eb620628364e" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "font-kit" -version = "0.11.0" +name = "font-kit" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21fe28504d371085fae9ac7a3450f0b289ab71e07c8e57baa3fb68b9e57d6ce5" dependencies = [ @@ -1747,20 +596,11 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -[[package]] -name = "form_urlencoded" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" -dependencies = [ - "percent-encoding", -] - [[package]] name = "freetype" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee38378a9e3db1cc693b4f88d166ae375338a0ff75cb8263e1c601d51f35dc6" +checksum = "efc8599a3078adf8edeb86c71e9f8fa7d88af5ca31e806a867756081f90f5d83" dependencies = [ "freetype-sys", "libc", @@ -1768,11 +608,11 @@ dependencies = [ [[package]] name = "freetype-sys" -version = "0.13.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +checksum = "66ee28c39a43d89fbed8b4798fb4ba56722cfd2b5af81f9326c27614ba88ecd5" dependencies = [ - "cmake", + "cc", "libc", "pkg-config", ] @@ -1784,2471 +624,792 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] -name = "futures" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[package]] -name = "futures-channel" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" -dependencies = [ - "futures-core", - "futures-sink", -] - -[[package]] -name = "futures-core" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" - -[[package]] -name = "futures-executor" -version = "0.3.29" +name = "generic-array" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ - "futures-core", - "futures-task", - "futures-util", + "serde", + "typenum", + "version_check", ] [[package]] -name = "futures-io" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" - -[[package]] -name = "futures-locks" -version = "0.7.1" +name = "getrandom" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45ec6fe3675af967e67c5536c0b9d44e34e6c52f86bedc4ea49c5317b8e94d06" -dependencies = [ - "futures-channel", - "futures-task", -] - -[[package]] -name = "futures-macro" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "futures-sink" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" - -[[package]] -name = "futures-task" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" - -[[package]] -name = "futures-timer" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" -dependencies = [ - "gloo-timers", - "send_wrapper 0.4.0", -] - -[[package]] -name = "futures-util" -version = "0.3.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" -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 = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", - "zeroize", -] - -[[package]] -name = "getrandom" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "libc", - "wasi", -] - -[[package]] -name = "gif" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" -dependencies = [ - "color_quant", - "weezl", -] - -[[package]] -name = "gimli" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" - -[[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core", - "subtle", -] - -[[package]] -name = "h2" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" -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_proofs" -version = "0.2.0" -source = "git+https://github.com/summa-dev/halo2#8386d6e64fc33baccf626869123185890b8284dc" -dependencies = [ - "blake2b_simd", - "ff", - "group", - "halo2curves", - "maybe-rayon", - "plotters", - "rand_chacha", - "rand_core", - "sha3 0.9.1", - "tabbycat", - "tracing", -] - -[[package]] -name = "halo2_solidity_verifier" -version = "0.1.0" -source = "git+https://github.com/summa-dev/halo2-solidity-verifier#d33972567f83f3218257b286b541ad97ba32928c" -dependencies = [ - "askama", - "blake2b_simd", - "halo2_proofs", - "hex", - "itertools 0.11.0", - "revm", - "ruint", - "sha3 0.10.8", -] - -[[package]] -name = "halo2curves" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6b1142bd1059aacde1b477e0c80c142910f1ceae67fc619311d6a17428007ab" -dependencies = [ - "blake2b_simd", - "ff", - "group", - "lazy_static", - "num-bigint", - "num-traits", - "pasta_curves", - "paste", - "rand", - "rand_core", - "static_assertions", - "subtle", -] - -[[package]] -name = "hashbrown" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" -dependencies = [ - "ahash", - "allocator-api2", -] - -[[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.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-literal" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" - -[[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 = "home" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "http" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" -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.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa", - "pin-project-lite", - "socket2 0.4.10", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.58" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "wasm-bindgen", - "windows-core", -] - -[[package]] -name = "iana-time-zone-haiku" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" -dependencies = [ - "cc", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "image" -version = "0.24.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f3dfdbdd72063086ff443e297b61695500514b1e41095b6fb9a5ab48a70a711" -dependencies = [ - "bytemuck", - "byteorder", - "color_quant", - "jpeg-decoder", - "num-rational", - "num-traits", - "png", -] - -[[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.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc88fc67028ae3db0c853baa36269d398d5f45b6982f95549ff5def78c935cd" -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 = "indenter" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" - -[[package]] -name = "indexmap" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" -dependencies = [ - "equivalent", - "hashbrown", -] - -[[package]] -name = "inout" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" -dependencies = [ - "generic-array", -] - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "ipnet" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" - -[[package]] -name = "is-terminal" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" -dependencies = [ - "hermit-abi 0.3.3", - "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 = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" - -[[package]] -name = "jpeg-decoder" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0000e42512c92e31c2252315bda326620a4e034105e900c98ec492fa077b3e" - -[[package]] -name = "js-sys" -version = "0.3.66" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "jsonwebtoken" -version = "8.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6971da4d9c3aa03c3d8f3ff0f4155b534aad021292003895a469716b2a230378" -dependencies = [ - "base64 0.21.5", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "k256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "sha2", - "signature", -] - -[[package]] -name = "keccak" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" -dependencies = [ - "cpufeatures", -] - -[[package]] -name = "lalrpop" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da4081d44f4611b66c6dd725e6de3169f9f63905421e8626fcb86b6a898998b8" -dependencies = [ - "ascii-canvas", - "bit-set", - "diff", - "ena", - "is-terminal", - "itertools 0.10.5", - "lalrpop-util", - "petgraph", - "regex", - "regex-syntax 0.7.5", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", -] - -[[package]] -name = "lalrpop-util" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f35c735096c0293d313e8f2a641627472b83d01b937177fe76e5e2708d31e0d" - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -dependencies = [ - "spin", -] - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "libc" -version = "0.2.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" - -[[package]] -name = "libloading" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] - -[[package]] -name = "libm" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" - -[[package]] -name = "libredox" -version = "0.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" -dependencies = [ - "bitflags 2.4.1", - "libc", - "redox_syscall", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" - -[[package]] -name = "lock_api" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" - -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", - "rayon", -] - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] - -[[package]] -name = "mime" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" - -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.48.0", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - -[[package]] -name = "nom" -version = "7.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" -dependencies = [ - "memchr", - "minimal-lexical", -] - -[[package]] -name = "num" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[package]] -name = "num-bigint" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", -] - -[[package]] -name = "num-complex" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" -dependencies = [ - "num-traits", -] - -[[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.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" -dependencies = [ - "autocfg", - "libm", -] - -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.3", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" -dependencies = [ - "proc-macro-crate 2.0.0", - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" - -[[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.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" - -[[package]] -name = "open-fastrlp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "786393f80485445794f6043fd3138854dd109cc6c4bd1a6383db304c9ce9b9ce" -dependencies = [ - "arrayvec", - "auto_impl", - "bytes", - "ethereum-types", - "open-fastrlp-derive", -] - -[[package]] -name = "open-fastrlp-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "003b2be5c6c53c1cfeb0a238b8a1c3915cd410feb684457a36c10038f764bb1c" -dependencies = [ - "bytes", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "parity-scale-codec" -version = "3.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dec8a8073036902368c2cdc0387e85ff9a37054d7e7c98e592145e0c92cd4fb" -dependencies = [ - "arrayvec", - "bitvec", - "byte-slice-cast", - "impl-trait-for-tuples", - "parity-scale-codec-derive", - "serde", -] - -[[package]] -name = "parity-scale-codec-derive" -version = "3.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312270ee71e1cd70289dacf597cab7b207aa107d2f28191c2ae45b2ece18a260" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[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", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets 0.48.5", -] - -[[package]] -name = "pasta_curves" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" -dependencies = [ - "blake2b_simd", - "ff", - "group", - "lazy_static", - "rand", - "static_assertions", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" - -[[package]] -name = "path-slash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e91099d4268b0e11973f036e885d652fb0b21fedcf69738c627f94db6a44f42" - -[[package]] -name = "pathfinder_geometry" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" -dependencies = [ - "log", - "pathfinder_simd", -] - -[[package]] -name = "pathfinder_simd" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0444332826c70dc47be74a7c6a5fc44e23a7905ad6858d4162b658320455ef93" -dependencies = [ - "rustc_version 0.4.0", -] - -[[package]] -name = "pbkdf2" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac", -] - -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - -[[package]] -name = "pem" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8835c273a76a90455d7344889b0964598e3316e2a79ede8e36f16bdcf2228b8" -dependencies = [ - "base64 0.13.1", -] - -[[package]] -name = "percent-encoding" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" - -[[package]] -name = "pest" -version = "2.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f200d8d83c44a45b21764d1916299752ca035d15ecd46faca3e9a2a2bf6ad06" -dependencies = [ - "memchr", - "thiserror", - "ucd-trie", -] - -[[package]] -name = "petgraph" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" -dependencies = [ - "fixedbitset", - "indexmap", -] - -[[package]] -name = "pharos" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" -dependencies = [ - "futures", - "rustc_version 0.4.0", -] - -[[package]] -name = "phf" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" -dependencies = [ - "phf_macros", - "phf_shared 0.11.2", -] - -[[package]] -name = "phf_generator" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" -dependencies = [ - "phf_shared 0.11.2", - "rand", -] - -[[package]] -name = "phf_macros" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" -dependencies = [ - "phf_generator", - "phf_shared 0.11.2", - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher", -] - -[[package]] -name = "phf_shared" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" -dependencies = [ - "siphasher", -] - -[[package]] -name = "pin-project" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[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.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" -dependencies = [ - "der", - "spki", -] - -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "plotters" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" -dependencies = [ - "chrono", - "font-kit", - "image", - "lazy_static", - "num-traits", - "pathfinder_geometry", - "plotters-backend", - "plotters-bitmap", - "plotters-svg", - "ttf-parser", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" - -[[package]] -name = "plotters-bitmap" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cebbe1f70205299abc69e8b295035bb52a6a70ee35474ad10011f0a4efb8543" -dependencies = [ - "gif", - "image", - "plotters-backend", -] - -[[package]] -name = "plotters-svg" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "png" -version = "0.17.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "powerfmt" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" - -[[package]] -name = "ppv-lite86" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "prettyplease" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d" -dependencies = [ - "proc-macro2", - "syn 2.0.39", -] - -[[package]] -name = "primitive-types" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b34d9fd68ae0b74a41b21c03c2f62847aa0ffea044eee893b4c140b37e244e2" -dependencies = [ - "fixed-hash", - "impl-codec", - "impl-rlp", - "impl-serde", - "scale-info", - "uint", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", -] - -[[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.70" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proptest" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" -dependencies = [ - "bitflags 2.4.1", - "lazy_static", - "num-traits", - "rand", - "rand_chacha", - "rand_xorshift", - "regex-syntax 0.8.2", - "unarray", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "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.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" -dependencies = [ - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" -dependencies = [ - "crossbeam-deque", - "crossbeam-utils", -] - -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_users" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-automata" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.2", -] - -[[package]] -name = "regex-syntax" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" - -[[package]] -name = "regex-syntax" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" - -[[package]] -name = "reqwest" -version = "0.11.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" -dependencies = [ - "base64 0.21.5", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "hyper", - "ipnet", - "js-sys", - "log", - "mime", - "once_cell", - "percent-encoding", - "pin-project-lite", - "serde", - "serde_json", - "serde_urlencoded", - "system-configuration", - "tokio", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg", -] - -[[package]] -name = "revm" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f4ca8ae0345104523b4af1a8a7ea97cfa1865cdb7a7c25d23c1a18d9b48598" -dependencies = [ - "auto_impl", - "revm-interpreter", - "revm-precompile", -] - -[[package]] -name = "revm-interpreter" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f959cafdf64a7f89b014fa73dc2325001cf654b3d9400260b212d19a2ebe3da0" -dependencies = [ - "revm-primitives", -] - -[[package]] -name = "revm-precompile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d360a88223d85709d2e95d4609eb1e19c649c47e28954bfabae5e92bb37e83e" -dependencies = [ - "c-kzg", - "k256", - "num", - "once_cell", - "revm-primitives", - "ripemd", - "secp256k1", - "sha2", - "substrate-bn", -] - -[[package]] -name = "revm-primitives" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51187b852d9e458816a2e19c81f1dd6c924077e1a8fccd16e4f044f865f299d7" -dependencies = [ - "alloy-primitives", - "alloy-rlp", - "auto_impl", - "bitflags 2.4.1", - "bitvec", - "c-kzg", - "enumn", - "hashbrown", - "hex", - "once_cell", -] - -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[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", + "wasi", ] [[package]] -name = "ripemd" -version = "0.1.3" +name = "gif" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +checksum = "80792593675e051cf94a4b111980da2ba60d4a83e43e0048c5693baab3977045" dependencies = [ - "digest 0.10.7", + "color_quant", + "weezl", ] [[package]] -name = "rlp" -version = "0.5.2" +name = "group" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb919243f34364b6bd2fc10ef797edbfa75f33c252e7998527479c6d6b47e1ec" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" dependencies = [ - "bytes", - "rlp-derive", - "rustc-hex", + "ff", + "rand_core", + "subtle", ] [[package]] -name = "rlp-derive" -version = "0.1.0" +name = "half" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33d7b2abe0c340d8797fe2907d3f20d3b5ea5908683618bfe80df7f621f672a" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "halo2_proofs" +version = "0.2.0" +source = "git+https://github.com/han0110/halo2.git?branch=feature/for-benchmark#4981b8d5bdaab04af9b56a5d2c482b6eec9f7fa4" dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", + "ark-std", + "blake2b_simd", + "ff", + "group", + "halo2curves 0.3.3", + "plotters", + "rand_chacha", + "rand_core", + "rayon", + "sha3 0.9.1", + "tabbycat", + "tracing", ] [[package]] -name = "ruint" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608a5726529f2f0ef81b8fde9873c4bb829d6b5b5ca6be4d97345ddf0749c825" +name = "halo2curves" +version = "0.3.2" +source = "git+https://github.com/privacy-scaling-explorations/halo2curves.git?tag=0.3.2#9f5c50810bbefe779ee5cf1d852b2fe85dc35d5e" dependencies = [ - "alloy-rlp", - "ark-ff 0.3.0", - "ark-ff 0.4.2", - "bytes", - "fastrlp", + "ff", + "group", + "lazy_static", "num-bigint", "num-traits", - "parity-scale-codec", - "primitive-types", - "proptest", + "pasta_curves", + "paste", "rand", - "rlp", - "ruint-macro", - "serde", - "valuable", - "zeroize", + "rand_core", + "static_assertions", + "subtle", ] [[package]] -name = "ruint-macro" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e666a5496a0b2186dbcd0ff6106e29e093c15591bde62c20d3842007c6978a09" - -[[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" +name = "halo2curves" version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee" +source = "git+https://github.com/privacy-scaling-explorations/halo2curves?tag=0.3.3#8e4cb9f0c66c864e8ca25da07f50ae95f664a5b7" dependencies = [ - "semver 0.11.0", + "ff", + "group", + "lazy_static", + "num-bigint", + "num-traits", + "pasta_curves", + "paste", + "rand", + "rand_core", + "serde", + "static_assertions", + "subtle", ] [[package]] -name = "rustc_version" -version = "0.4.0" +name = "hermit-abi" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" dependencies = [ - "semver 1.0.20", + "libc", ] [[package]] -name = "rustix" -version = "0.38.25" +name = "hex" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" dependencies = [ - "bitflags 2.4.1", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", + "serde", ] [[package]] -name = "rustversion" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" - -[[package]] -name = "ryu" -version = "1.0.15" +name = "iana-time-zone" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] [[package]] -name = "salsa20" -version = "0.10.2" +name = "iana-time-zone-haiku" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" dependencies = [ - "cipher", + "cc", ] [[package]] -name = "same-file" -version = "1.0.6" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] -name = "scale-info" -version = "2.10.0" +name = "image" +version = "0.24.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7d66a1128282b7ef025a8ead62a4a9fcf017382ec53b8ffbf4d7bf77bd3c60" +checksum = "5690139d2f55868e080017335e4b94cb7414274c74f1669c84fb5feba2c9f69d" dependencies = [ - "cfg-if", - "derive_more", - "parity-scale-codec", - "scale-info-derive", + "bytemuck", + "byteorder", + "color_quant", + "jpeg-decoder", + "num-traits", + "png", ] [[package]] -name = "scale-info-derive" -version = "2.10.0" +name = "itertools" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf2c68b89cafb3b8d918dd07b42be0da66ff202cf1155c5739a4e0c1ea0dc19" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", + "either", ] [[package]] -name = "scopeguard" -version = "1.2.0" +name = "itoa" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] -name = "scrypt" -version = "0.10.0" +name = "jpeg-decoder" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d" -dependencies = [ - "hmac", - "pbkdf2 0.11.0", - "salsa20", - "sha2", -] +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" [[package]] -name = "sec1" -version = "0.7.3" +name = "js-sys" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", + "wasm-bindgen", ] [[package]] -name = "secp256k1" -version = "0.27.0" +name = "keccak" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25996b82292a7a57ed3508f052cfff8640d38d32018784acd714758b43da9c8f" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ - "secp256k1-sys", + "cpufeatures", ] [[package]] -name = "secp256k1-sys" -version = "0.8.1" +name = "lazy_static" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a129b9e9efbfb223753b9163c4ab3b13cff7fd9c7f010fbac25ab4099fa07e" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" dependencies = [ - "cc", + "spin", ] [[package]] -name = "semver" -version = "0.11.0" +name = "libc" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" -dependencies = [ - "semver-parser", -] +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] -name = "semver" -version = "1.0.20" +name = "libloading" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ - "serde", + "cfg-if", + "windows-targets", ] [[package]] -name = "semver-parser" -version = "0.10.2" +name = "libredox" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0bef5b7f9e0df16536d3961cfb6e84331c065b4066afb39768d0e319411f7" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "pest", + "bitflags 2.5.0", + "libc", ] [[package]] -name = "send_wrapper" -version = "0.4.0" +name = "log" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f638d531eccd6e23b980caf34876660d38e265409d8e99b397ab71eb3612fad0" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] -name = "send_wrapper" -version = "0.6.0" +name = "memchr" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] -name = "serde" -version = "1.0.193" +name = "miniz_oxide" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ - "serde_derive", + "adler", + "simd-adler32", ] [[package]] -name = "serde_cbor" -version = "0.11.2" +name = "num-bigint" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ - "half", - "serde", + "autocfg", + "num-integer", + "num-traits", ] [[package]] -name = "serde_derive" -version = "1.0.193" +name = "num-integer" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", + "num-traits", ] [[package]] -name = "serde_json" -version = "1.0.108" +name = "num-traits" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ - "itoa", - "ryu", - "serde", + "autocfg", ] [[package]] -name = "serde_spanned" -version = "0.6.4" +name = "once_cell" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12022b835073e5b11e90a14f86838ceb1c8fb0325b72416845c487ac0fa95e80" -dependencies = [ - "serde", -] +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "oorandom" +version = "11.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "pasta_curves" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "d3e57598f73cc7e1b2ac63c79c517b31a0877cd7c402cdcaa311b5208de7a095" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", + "blake2b_simd", + "ff", + "group", + "hex", + "lazy_static", + "rand", "serde", + "static_assertions", + "subtle", ] [[package]] -name = "sha2" -version = "0.10.8" +name = "paste" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] -name = "sha3" -version = "0.9.1" +name = "pathfinder_geometry" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" +checksum = "0b7b7e7b4ea703700ce73ebf128e1450eb69c3a8329199ffbfb9b2a0418e5ad3" dependencies = [ - "block-buffer 0.9.0", - "digest 0.9.0", - "keccak", - "opaque-debug", + "log", + "pathfinder_simd", ] [[package]] -name = "sha3" -version = "0.10.8" +name = "pathfinder_simd" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +checksum = "ebf45976c56919841273f2a0fc684c28437e2f304e264557d9c72be5d5a718be" dependencies = [ - "digest 0.10.7", - "keccak", + "rustc_version", ] [[package]] -name = "shlex" -version = "1.2.0" +name = "pin-project-lite" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] -name = "signature" -version = "2.2.0" +name = "pkg-config" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core", -] +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +name = "plonkish_backend" +version = "0.1.0" +source = "git+https://github.com/han0110/plonkish#303cf244803ea56d1ac8c24829ec4c67e4e798ab" +dependencies = [ + "bincode", + "bitvec", + "generic-array", + "halo2_proofs", + "halo2curves 0.3.3", + "itertools", + "num-bigint", + "num-integer", + "pasta_curves", + "poseidon", + "rand", + "rayon", + "serde", + "sha3 0.10.8", +] [[package]] -name = "simple_asn1" -version = "0.6.2" +name = "plotters" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ - "num-bigint", + "chrono", + "font-kit", + "image", + "lazy_static", "num-traits", - "thiserror", - "time", + "pathfinder_geometry", + "plotters-backend", + "plotters-bitmap", + "plotters-svg", + "ttf-parser", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "siphasher" -version = "0.3.11" +name = "plotters-backend" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] -name = "slab" -version = "0.4.9" +name = "plotters-bitmap" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "0cebbe1f70205299abc69e8b295035bb52a6a70ee35474ad10011f0a4efb8543" dependencies = [ - "autocfg", + "gif", + "image", + "plotters-backend", ] [[package]] -name = "smallvec" -version = "1.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" - -[[package]] -name = "socket2" -version = "0.4.10" +name = "plotters-svg" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ - "libc", - "winapi", + "plotters-backend", ] [[package]] -name = "socket2" -version = "0.5.5" +name = "png" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ - "libc", - "windows-sys 0.48.0", + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", ] [[package]] -name = "solang-parser" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c425ce1c59f4b154717592f0bdf4715c3a1d55058883622d3157e1f0908a5b26" +name = "poseidon" +version = "0.2.0" +source = "git+https://github.com/han0110/poseidon?branch=feature/with-spec#fa4c2544ed38666f1f72d1c4fd0956756a7112b3" dependencies = [ - "itertools 0.11.0", - "lalrpop", - "lalrpop-util", - "phf", - "thiserror", - "unicode-xid", + "halo2curves 0.3.2", + "subtle", ] [[package]] -name = "spin" -version = "0.5.2" +name = "ppv-lite86" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] -name = "spki" -version = "0.7.2" +name = "proc-macro2" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "a56dea16b0a29e94408b9aa5e2940a4eedbd128a1ba20e8f7ae60fd3d465af0e" dependencies = [ - "base64ct", - "der", + "unicode-ident", ] [[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "string_cache" -version = "0.8.7" +name = "quote" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot", - "phf_shared 0.10.0", - "precomputed-hash", + "proc-macro2", ] [[package]] -name = "strsim" -version = "0.9.3" +name = "radium" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] -name = "strum" -version = "0.25.0" +name = "rand" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "strum_macros", + "libc", + "rand_chacha", + "rand_core", ] [[package]] -name = "strum_macros" -version = "0.25.3" +name = "rand_chacha" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ - "heck", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.39", + "ppv-lite86", + "rand_core", ] [[package]] -name = "substrate-bn" -version = "0.6.0" +name = "rand_core" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b5bbfa79abbae15dd642ea8176a21a635ff3c00059961d1ea27ad04e5b441c" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "byteorder", - "crunchy", - "lazy_static", - "rand", - "rustc-hex", + "getrandom", ] [[package]] -name = "subtle" -version = "2.5.0" +name = "rayon" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" - -[[package]] -name = "summa-solvency" -version = "0.2.0" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ - "ark-std 0.3.0", - "criterion", - "csv", - "ethers", - "halo2_proofs", - "halo2_solidity_verifier", - "hex", - "itertools 0.10.5", - "num-bigint", - "num-traits", - "num_cpus", - "plotters", - "rand", - "rayon", - "regex", - "serde", - "serde_json", - "tabbycat", + "either", + "rayon-core", ] [[package]] -name = "syn" -version = "1.0.109" +name = "rayon-core" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "crossbeam-deque", + "crossbeam-utils", ] [[package]] -name = "syn" -version = "2.0.39" +name = "redox_users" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "getrandom", + "libredox", + "thiserror", ] [[package]] -name = "system-configuration" -version = "0.5.1" +name = "regex" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "system-configuration-sys", + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", ] [[package]] -name = "system-configuration-sys" -version = "0.5.0" +name = "regex-automata" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ - "core-foundation-sys", - "libc", + "aho-corasick", + "memchr", + "regex-syntax", ] [[package]] -name = "tabbycat" -version = "0.1.2" +name = "regex-syntax" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c45590f0f859197b4545be1b17b2bc3cc7bb075f7d1cc0ea1dc6521c0bf256a3" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "anyhow", - "derive_builder", - "regex", + "semver", ] [[package]] -name = "tap" -version = "1.0.1" +name = "ryu" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] -name = "tempfile" -version = "3.8.1" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys 0.48.0", + "winapi-util", ] [[package]] -name = "term" -version = "0.7.0" +name = "semver" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] -name = "textwrap" -version = "0.11.0" +name = "serde" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ - "unicode-width", + "serde_derive", ] [[package]] -name = "thiserror" -version = "1.0.50" +name = "serde_cbor" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ - "thiserror-impl", + "half", + "serde", ] [[package]] -name = "thiserror-impl" -version = "1.0.50" +name = "serde_derive" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.59", ] [[package]] -name = "threadpool" -version = "1.8.1" +name = "serde_json" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ - "num_cpus", + "itoa", + "ryu", + "serde", ] [[package]] -name = "time" -version = "0.3.30" +name = "sha3" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "deranged", - "itoa", - "powerfmt", - "serde", - "time-core", - "time-macros", + "block-buffer 0.9.0", + "digest 0.9.0", + "keccak", + "opaque-debug", ] [[package]] -name = "time-core" -version = "0.1.2" +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 = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "time-macros" -version = "0.2.15" +name = "strsim" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" -dependencies = [ - "time-core", -] +checksum = "6446ced80d6c486436db5c078dde11a9f73d42b57fb273121e160b84f63d894c" [[package]] -name = "tiny-keccak" -version = "2.0.2" +name = "subtle" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +name = "summa-hyperplonk" +version = "0.3.0" dependencies = [ - "serde", - "serde_json", + "criterion", + "csv", + "halo2_proofs", + "num-bigint", + "plonkish_backend", + "plotters", + "rand", + "rayon", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "syn" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "tinyvec_macros", + "proc-macro2", + "quote", + "unicode-ident", ] [[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.34.0" +name = "syn" +version = "2.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "4a6531ffc7b071655e4ce2e04bd464c4830bb585a61cabb96cf808f05172615a" dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "pin-project-lite", - "socket2 0.5.5", - "windows-sys 0.48.0", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] -name = "tokio-util" -version = "0.7.10" +name = "tabbycat" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "c45590f0f859197b4545be1b17b2bc3cc7bb075f7d1cc0ea1dc6521c0bf256a3" dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", + "anyhow", + "derive_builder", + "regex", ] [[package]] -name = "toml" -version = "0.8.8" +name = "tap" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.21.0", -] +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] -name = "toml_datetime" -version = "0.6.5" +name = "textwrap" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "serde", + "unicode-width", ] [[package]] -name = "toml_edit" -version = "0.19.15" +name = "thiserror" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ - "indexmap", - "toml_datetime", - "winnow", + "thiserror-impl", ] [[package]] -name = "toml_edit" -version = "0.20.7" +name = "thiserror-impl" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ - "indexmap", - "toml_datetime", - "winnow", + "proc-macro2", + "quote", + "syn 2.0.59", ] [[package]] -name = "toml_edit" -version = "0.21.0" +name = "tinytemplate" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ - "indexmap", "serde", - "serde_spanned", - "toml_datetime", - "winnow", + "serde_json", ] -[[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.40" @@ -4268,7 +1429,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.59", ] [[package]] @@ -4280,22 +1441,6 @@ 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 = "ttf-parser" version = "0.17.1" @@ -4308,105 +1453,18 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "ucd-trie" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" - -[[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 = "unarray" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" - -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[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.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[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-width" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" -[[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.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", -] - -[[package]] -name = "uuid" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" -dependencies = [ - "getrandom", - "serde", -] - -[[package]] -name = "valuable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" - [[package]] name = "version_check" version = "0.9.4" @@ -4415,23 +1473,14 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -4440,9 +1489,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4450,36 +1499,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.59", "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" -dependencies = [ - "cfg-if", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4487,28 +1524,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.59", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.65" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -4516,21 +1553,9 @@ dependencies = [ [[package]] name = "weezl" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb" - -[[package]] -name = "which" -version = "4.4.2" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix", -] +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "winapi" @@ -4565,163 +1590,76 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" -dependencies = [ - "windows-targets 0.48.5", -] - -[[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.5", -] - -[[package]] -name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" -dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows-targets", ] [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" [[package]] -name = "windows_i686_msvc" -version = "0.48.5" +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" - -[[package]] -name = "winnow" -version = "0.5.19" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829846f3e3db426d4cee4510841b71a8e58aa2a76b1132579487ae430ccd9c7b" -dependencies = [ - "memchr", -] - -[[package]] -name = "winreg" -version = "0.50.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" -dependencies = [ - "cfg-if", - "windows-sys 0.48.0", -] +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "wio" @@ -4732,25 +1670,6 @@ 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 0.4.0", - "send_wrapper 0.6.0", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "wyz" version = "0.5.1" @@ -4760,12 +1679,6 @@ dependencies = [ "tap", ] -[[package]] -name = "yansi" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" - [[package]] name = "yeslogic-fontconfig-sys" version = "3.2.0" @@ -4777,43 +1690,3 @@ dependencies = [ "once_cell", "pkg-config", ] - -[[package]] -name = "zerocopy" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.7.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] - -[[package]] -name = "zeroize" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.39", -] diff --git a/prover/Cargo.toml b/prover/Cargo.toml index 435f5692..f469265c 100644 --- a/prover/Cargo.toml +++ b/prover/Cargo.toml @@ -1,46 +1,33 @@ [package] -name = "summa-solvency" -version = "0.2.0" +name = "summa-hyperplonk" +version = "0.3.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] dev-graph = ["halo2_proofs/dev-graph", "plotters"] -profiling = [] -no_range_check = [] +default = ["parallel", "frontend-halo2"] +parallel = ["dep:rayon"] +frontend-halo2 = ["dep:halo2_proofs"] [dependencies] -halo2_proofs = { git = "https://github.com/summa-dev/halo2"} +plonkish_backend = { git = "https://github.com/han0110/plonkish", package = "plonkish_backend", features= ["frontend-halo2", "benchmark"] } plotters = { version = "0.3.4", optional = true } rand = "0.8" -ark-std = { version = "0.3.0", features = ["print-trace"] } -tabbycat = { version = "0.1", features = ["attributes"], optional = true } csv = "1.1" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -hex = "0.4.3" num-bigint = "0.4" -num_cpus = "1.15" -itertools = "0.10.3" -ethers = { version = "2.0.7", default-features = false, features = ["ethers-solc"] } -regex-simple = { version = "1", package = "regex" } -num-traits = "0.2.16" -rayon = "1.8.0" -halo2_solidity_verifier = { git = "https://github.com/summa-dev/halo2-solidity-verifier", version = "0.1.0", features = ["evm"] } + +# parallel +rayon = { version = "1.5.3", optional = true } + +# frontend-halo2 +halo2_proofs = { git = "https://github.com/han0110/halo2.git", branch = "feature/for-benchmark", optional = true } [dev-dependencies] criterion= "0.3" [[bench]] -name = "kzg" -harness = false - -[[bin]] -name = "generate_verifier" -path = "bin/gen_verifier.rs" - -[[bin]] -name = "generate_commitment_and_proofs" -path = "bin/gen_commit_and_proofs.rs" +name = "proof_of_liabilities" +harness = false \ No newline at end of file diff --git a/prover/README.md b/prover/README.md index 31a3fc79..9cc6edcf 100644 --- a/prover/README.md +++ b/prover/README.md @@ -1,36 +1,7 @@ -# Summa V2: Polynomial Interpolation Approach +# Summa V3: Hyperplonk Prover ## Motivation -[Summa V1](https://github.com/summa-dev/summa-solvency/releases/tag/merkle_sum_tree_v1.1.1) was using a Merkle sum tree (MST) as the main data structure and a cryptographic commitment. MST that has $n$ leaves involves $2n-1$ hashing operations, making it computationally demanding. Additionally, the MST inclusion proofs in Summa V1 have to be wrapped into a ZK-SNARK, making it infeasible to generate all of them at once for the entire user base of the Custodian (~100M users). - -## Univariate Grand Sum Calculation - -The grand total of all the Custodian's $n$ user cryptocurrency balances is the Custodian's liabilities $S$. Summa V2 is using a property of the _sum of all roots of unity in a finite field_ being _equal to zero_ to find the liabilities. This property allows to efficiently calculate the grand sum of univariate polynomial evaluations. Summa V2 takes advantage of that by interpolating the user balances into a univariate polynomial in a special way. The resulting proof of solvency protocol has the following steps: - -1. construct a polynomial of degree $d = n - 1$ that interpolates the points $(\omega^i, b_i)$ where $i \in 0..n-1$ is the user index, $\omega^i$ is the power of an $n$-th primitive root of unity ($x$ value), and $b_i$ is the $i$-th user balance value ($y$ value); -2. multiply the constant term $a_0$ of the polynomial by $n$ to obtain the grand sum: - $\begin{equation}\boxed{S = a_0n= \sum_{i=0}^{n-1}b_i};\end{equation}$ -3. use a polynomial commitment scheme to provide opening proofs to the individual users and a public $a_0$ opening at $x=0$. - -Please refer to the [article](https://hackmd.io/@summa/BkglBWsDp) for the detailed description of the algorithm. - -## Algorithm Implementation - -Halo2 allows to efficiently implement the described algorithm for the following reasons: - -- the advice columns in Halo2 are interpolated as polynomials, and the $x$ values are the powers of a primitive root of unity; -- Halo2 is internally using a KZG polynomial commitment scheme; -- the use of a ZK-SNARK allows to additionally constrain the balance values, namely, perform the range check. - -The algorithm works as follows: - -1. Assign all the user balances to an unblinded advice column of the [circuit](../prover/src/circuits/univariate_grand_sum.rs). The unblinded advice column is a special kind of advice column without the random values (blinding factors) added at the bottom. The constant term of such polynomial correctly yields the grand total of user balances according to (1) because the polynomial only interpolates the user balances but not the blinding factors (as in the case with a normal advice column). -2. Assign the user IDs (e.g., hashes of user emails) to another (normal) advice column. -3. Generate the ZK-SNARK proof for the circuit, effectively interpolating the balance values into a polynomial and performing a KZG commitment to this polynomial. -4. Perform a KZG opening proof of the polynomial at $x=0$ and publicly reveal the constant term $a_0$ of the polynomial. The public can then calculate the liabilities by multiplying the $a_0$ by $d + 1$ where $d$ is the polynomial degree. -5. Privately provide to each user a KZG proof of the corresponding user opening (namely, the openings of the user ID and balance polynomials). Cross-checking the balance opening and the user ID opening $\omega^i$ value ensures that no malicious Custodian can provide the same balance opening to multiple users with the identical balance value. - ## Usage To build, test and print the circuits, execute @@ -40,77 +11,13 @@ cargo build cargo test --release --features dev-graph ``` -To generate the solidity verifier that can verify the SNARK proof, execute the following command: - -``` -cargo run --bin generate_verifier -``` - -This process will generate the verifier, `SnarkVerifier.sol`, which will be located in `../contracts/src`. - -To generate commitments and proofs with the sample data located in `entry_16.csv` at `../csv/`, execute: - -``` -cargo run --bin generate_commitment_and_proofs -``` - -This script will generate `commitment_solidity_calldata.json` and `inclusion_proof_solidity_calldata.json` in the `prover/bin`.
-These two JSON files will be used for testing in the `contracts`. - -## Documentation - -The documentation for the circuits can be generated by running - -``` -cargo doc --no-deps --open -``` - -## Powers of Tau Trusted Setup - -For testing purposes, it's not necessary to download the `ptau` file. The `generate_setup_artifacts` function can manage this by generating a new setup from a randomly generated value. This automated generation process is intended for testing and development convenience, and it should not be used in production. -For real-world situations, you must provide the path of a specific `ptau` file to the `generate_setup_artifacts`. The circuit will use the randomness from the given file. You can find an example that initializes a `Snapshot` instance [here](https://github.com/summa-dev/summa-solvency/blob/11d4fce5d18f6175804aa792fc9fc5ac27bf5c00/backend/src/apis/snapshot.rs#L115-L116) in the backend. - ## Benchmarks The following benchmarks are available in the `kzg` module: -- `range_check_proof`: the zk-SNARK proof generation time of the polynomial interpolation of user balances with range check; -- `opening_grand_sum`: the time to generate the KZG opening proof of the grand sum of user balances; -- `opening_user`: the time to generate the KZG opening proof of a single user inclusion; -- `calculate_h`: the time to calculate the h(X) for the amortized KZG approach; -- `amortized_opening_all`: the time to generate open proofs for all 2^K user inclusions using the amortized approach; -- `amortized_opening_user`: the time to generate the KZG opening proof of a single user inclusion using the precomputed h(x) from the amortized approach; -- `verifying_grand_sum`: the time to verify the KZG opening proof of the grand sum of user balances; -- `verifying_user`: the time to verify the KZG opening proof of a single user inclusion. - -To run the benchmarks with the default full configuration of the circuit (range check enabled), use the following command: +- `grand sum proof`: the time to generate a ZK-SNARK proof of the grand sum with a range check of every balance; + To run the benchmarks with the default full configuration of the circuit (range check enabled), use the following command: ```shell cargo bench ``` - -To run the quick benchmarks with the range check disabled (K=9..12), use the following command: - -```shell -cargo bench --features "no_range_check" -``` - -## Chunked Univariate Grand Sum Example - -the following technique is proposed to further improve the performance of the univariate grand sum version of Summa: - -1. Split the user base into chunks; -2. Generate the zkSNARK range proof for all the users of each chunk (one proof per chunk) alongside with the advice polynomials; -3. Generate the proofs of inclusion of a user into a specific chunk; -4. Prove the grand total across the chunks by performing the following: - 1. Add together the chunk polynomials generated in step 2; - 2. Add their corresponding KZG commitments together using the homomorphic property of the KZG commitment; - 3. Generate the opening proof of the grand sum for the resulting polynomial from step 4.1 against the commitment from step 4.3 - -Step 4 of the algorithm establishes the relation between the chunks containing individual user liabilities and the grand sum of all user liabilities. The proof of inclusion generation in step 3 should be carried out using the amortized KZG approach in the similar fashion as in the non-chunked version of Summa. - -The proof of concept implementation of the suggested approach can be found in the [example file](prover/examples/chunked_univariate_grand_sum.rs). To execute the example, use the command: - -```shell -cargo run --release --example chunked_univariate_grand_sum -``` diff --git a/prover/benches/kzg.rs b/prover/benches/kzg.rs deleted file mode 100644 index 471bca8c..00000000 --- a/prover/benches/kzg.rs +++ /dev/null @@ -1,306 +0,0 @@ -#![feature(generic_const_exprs)] -use criterion::{criterion_group, criterion_main, Criterion}; -use halo2_proofs::{arithmetic::Field, halo2curves::bn256::Fr as Fp}; -use num_bigint::BigUint; -use rand::{rngs::OsRng, Rng}; - -#[cfg(feature = "no_range_check")] -use summa_solvency::circuits::univariate_grand_sum::NoRangeCheckConfig; -#[cfg(not(feature = "no_range_check"))] -use summa_solvency::circuits::univariate_grand_sum::UnivariateGrandSumConfig; -use summa_solvency::{ - circuits::{ - univariate_grand_sum::{CircuitConfig, UnivariateGrandSum}, - utils::{ - compute_h_parallel, full_prover, generate_setup_artifacts, - open_all_user_points_amortized, open_grand_sums, open_grand_sums_gwc, - open_single_user_point_amortized, open_user_points, verify_grand_sum_openings, - verify_user_inclusion, - }, - }, - utils::{big_uint_to_fp, generate_dummy_entries}, -}; - -fn bench_kzg< - const K: u32, - const N_USERS: usize, - const N_CURRENCIES: usize, - CONFIG: CircuitConfig, ->( - name: &str, -) where - [(); N_CURRENCIES + 1]:, -{ - let mut c = Criterion::default().sample_size(10); - - // Initialize an empty circuit - let circuit = UnivariateGrandSum::::init_empty(); - let (params, pk, vk) = generate_setup_artifacts(K, None, &circuit).unwrap(); - - let range_check_proof_bench_name = format!("<{}> range check", name); - let opening_grand_sum_bench_name = format!("<{}> opening grand sum", name); - let opening_user_bench_name = format!("<{}> opening single user inclusion", name); - let calculate_h_bench_name = - format!("<{}> calculating h(X) for the amortized KZG approach", name); - let amortized_opening_all_bench_name = format!( - "<{}> opening all 2^{} user inclusions using the amortized approach", - name, K - ); - let amortized_opening_user_bench_name = format!( - "<{}> opening single user inclusion using the amortized approach", - name - ); - let verifying_grand_sum_bench_name = format!("<{}> verifying grand sum", name); - let verifying_user_bench_name = format!("<{}> verifying user inclusion", name); - - let entries = generate_dummy_entries::().unwrap(); - - // Calculate total for all entry columns - let mut total_balances: Vec = vec![BigUint::from(0u32); N_CURRENCIES]; - - for entry in &entries { - for (i, balance) in entry.balances().iter().enumerate() { - total_balances[i] += balance; - } - } - - let circuit = UnivariateGrandSum::::init(entries.to_vec()); - - c.bench_function(&range_check_proof_bench_name, |b| { - b.iter_batched( - || circuit.clone(), // Setup function: clone the circuit for each iteration - |circuit| { - full_prover(¶ms, &pk, circuit, &[vec![Fp::zero()]]); - }, - criterion::BatchSize::SmallInput, // Choose an appropriate batch size - ); - }); - - let (zk_snark_proof, advice_polys, omega) = - full_prover(¶ms, &pk, circuit, &[vec![Fp::zero()]]); - - let poly_length = 1 << u64::from(K); - - c.bench_function(&opening_grand_sum_bench_name, |b| { - b.iter_batched( - || 1..N_CURRENCIES + 1, - |balance_column_range| { - open_grand_sums( - &advice_polys.advice_polys, - &advice_polys.advice_blinds, - ¶ms, - balance_column_range, - total_balances - .iter() - .map(|x| big_uint_to_fp(&(x)) * Fp::from(poly_length).invert().unwrap()) - .collect::>() - .as_slice(), - ) - }, - criterion::BatchSize::SmallInput, - ); - }); - - c.bench_function(&format!("{} gwc", opening_grand_sum_bench_name), |b| { - b.iter_batched( - || 1..N_CURRENCIES + 1, - |balance_column_range| { - open_grand_sums_gwc( - &advice_polys.advice_polys, - &advice_polys.advice_blinds, - ¶ms, - balance_column_range, - total_balances - .iter() - .map(|x| big_uint_to_fp(&(x)) * Fp::from(poly_length).invert().unwrap()) - .collect::>() - .as_slice(), - ) - }, - criterion::BatchSize::SmallInput, - ); - }); - - // Generate a random user index - let get_random_user_index = || { - let user_range: std::ops::Range = 0..N_USERS; - OsRng.gen_range(user_range) as u16 - }; - - c.bench_function(&opening_user_bench_name, |b| { - b.iter_batched( - || (get_random_user_index(), 0..N_CURRENCIES + 1), - |(user_index, column_range)| { - open_user_points( - &advice_polys.advice_polys, - &advice_polys.advice_blinds, - ¶ms, - column_range, - omega, - user_index, - &entries - .get(user_index as usize) - .map(|entry| { - std::iter::once(big_uint_to_fp(&(entry.username_as_big_uint()))) - .chain(entry.balances().iter().map(|x| big_uint_to_fp(x))) - .collect::>() - }) - .unwrap(), - ) - }, - criterion::BatchSize::SmallInput, - ); - }); - - c.bench_function(&calculate_h_bench_name, |b| { - b.iter_batched( - || (0..N_CURRENCIES + 1), - |column_range| compute_h_parallel(&advice_polys.advice_polys, ¶ms, column_range), - criterion::BatchSize::SmallInput, - ); - }); - - let h_vectors = compute_h_parallel(&advice_polys.advice_polys, ¶ms, 0..N_CURRENCIES + 1); - let vec_of_slices = h_vectors.iter().map(|v| v.as_slice()).collect::>(); - let h_slices = vec_of_slices.as_slice(); - - c.bench_function(&amortized_opening_all_bench_name, |b| { - b.iter_batched( - || {}, - |_| open_all_user_points_amortized(h_slices, omega), - criterion::BatchSize::SmallInput, - ); - }); - - c.bench_function(&amortized_opening_user_bench_name, |b| { - b.iter_batched( - || {}, - |_| open_single_user_point_amortized(h_slices, ¶ms, omega), - criterion::BatchSize::SmallInput, - ); - }); - - // Open grand sum for benchmark verifying grand sum - let balance_column_range = 1..N_CURRENCIES + 1; - let grand_sums_batch_proof = open_grand_sums( - &advice_polys.advice_polys, - &advice_polys.advice_blinds, - ¶ms, - balance_column_range.clone(), - total_balances - .iter() - .map(|x| big_uint_to_fp(&(x)) * Fp::from(poly_length).invert().unwrap()) - .collect::>() - .as_slice(), - ); - - c.bench_function(&verifying_grand_sum_bench_name, |b| { - b.iter_batched( - || { - ( - grand_sums_batch_proof.clone(), - u64::try_from(advice_polys.advice_polys[0].len()).unwrap(), - balance_column_range.clone(), - ) - }, - |(grand_sums_batch_proof, poly_length, balance_column_range)| { - verify_grand_sum_openings::( - ¶ms, - &zk_snark_proof, - &grand_sums_batch_proof, - poly_length, - balance_column_range, - ) - }, - criterion::BatchSize::SmallInput, - ); - }); - - // Open user inclusion for benchmark verifying user inclusion - let column_range = 0..N_CURRENCIES + 1; - let omega = vk.get_domain().get_omega(); - let user_index = get_random_user_index(); - let openings_batch_proof = open_user_points( - &advice_polys.advice_polys, - &advice_polys.advice_blinds, - ¶ms, - column_range.clone(), - omega, - user_index, - &entries - .get(user_index as usize) - .map(|entry| { - std::iter::once(big_uint_to_fp(&(entry.username_as_big_uint()))) - .chain(entry.balances().iter().map(|x| big_uint_to_fp(x))) - .collect::>() - }) - .unwrap(), - ); - - c.bench_function(&verifying_user_bench_name, |b| { - b.iter_batched( - || (column_range.clone(), omega, user_index), - |(column_range, omega, user_index)| { - verify_user_inclusion( - ¶ms, - &zk_snark_proof, - &openings_batch_proof, - column_range, - omega, - user_index, - ); - }, - criterion::BatchSize::SmallInput, - ); - }); -} - -fn criterion_benchmark(_c: &mut Criterion) { - const N_CURRENCIES: usize = 1; - - // Demonstrating that a higher value of K has a more significant impact on benchmark performance than the number of users - #[cfg(not(feature = "no_range_check"))] - { - const K: u32 = 17; - const N_USERS: usize = 2usize.pow(K) - 6; - bench_kzg::>( - format!("K = {K}, N_USERS = {N_USERS}, N_CURRENCIES = {N_CURRENCIES}").as_str(), - ); - } - //Use the following benchmarks for quick evaluation/prototyping (no range check) - #[cfg(feature = "no_range_check")] - { - const K: u32 = 9; - const N_USERS: usize = 2usize.pow(K) - 6; - bench_kzg::>( - format!("K = {K}, N_USERS = {N_USERS}, N_CURRENCIES = {N_CURRENCIES}").as_str(), - ); - } - #[cfg(feature = "no_range_check")] - { - const K: u32 = 10; - const N_USERS: usize = 2usize.pow(K) - 6; - bench_kzg::>( - format!("K = {K}, N_USERS = {N_USERS}, N_CURRENCIES = {N_CURRENCIES}").as_str(), - ); - } - #[cfg(feature = "no_range_check")] - { - const K: u32 = 11; - const N_USERS: usize = 2usize.pow(K) - 6; - bench_kzg::>( - format!("K = {K}, N_USERS = {N_USERS}, N_CURRENCIES = {N_CURRENCIES}").as_str(), - ); - } - #[cfg(feature = "no_range_check")] - { - const K: u32 = 12; - const N_USERS: usize = 2usize.pow(K) - 6; - bench_kzg::>( - format!("K = {K}, N_USERS = {N_USERS}, N_CURRENCIES = {N_CURRENCIES}").as_str(), - ); - } -} - -criterion_group!(benches, criterion_benchmark); -criterion_main!(benches); diff --git a/prover/benches/proof_of_liabilities.rs b/prover/benches/proof_of_liabilities.rs new file mode 100644 index 00000000..b60fe012 --- /dev/null +++ b/prover/benches/proof_of_liabilities.rs @@ -0,0 +1,87 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use plonkish_backend::{ + backend::{hyperplonk::HyperPlonk, PlonkishBackend, PlonkishCircuit, PlonkishCircuitInfo}, + frontend::halo2::Halo2Circuit, + halo2_curves::bn256::{Bn256, Fr as Fp}, + pcs::multilinear::MultilinearKzg, + util::{ + test::std_rng, + transcript::{InMemoryTranscript, Keccak256Transcript}, + }, +}; +use rand::{ + rngs::{OsRng, StdRng}, + CryptoRng, RngCore, SeedableRng, +}; +use summa_hyperplonk::{ + circuits::summa_circuit::summa_hyperplonk::SummaHyperplonk, utils::generate_dummy_entries, +}; + +fn bench_summa() { + let name = format!("K = {K}, N_USERS = {N_USERS}, N_CURRENCIES = {N_CURRENCIES}"); + let mut c = Criterion::default().sample_size(10); + + let grand_sum_proof_bench_name = format!("<{}> grand sum proof", name); + + type Pb = HyperPlonk>; + let entries = generate_dummy_entries::().unwrap(); + let halo2_circuit = SummaHyperplonk::::init(entries.to_vec()); + + let circuit = Halo2Circuit::>::new::( + 17, + halo2_circuit.clone(), + ); + + let circuit_info: PlonkishCircuitInfo<_> = circuit.circuit_info().unwrap(); + let instances = circuit.instances(); + let param = Pb::setup(&circuit_info, seeded_std_rng()).unwrap(); + + let (pp, vp) = Pb::preprocess(¶m, &circuit_info).unwrap(); + + let mut transcript = Keccak256Transcript::default(); + let proof = { + Pb::prove(&pp, &circuit, &mut transcript, std_rng()).unwrap(); + transcript.into_proof() + }; + + let accept = { + let mut transcript = Keccak256Transcript::from_proof((), proof.as_slice()); + Pb::verify(&vp, instances, &mut transcript, std_rng()).is_ok() + }; + assert!(accept); + + c.bench_function(&grand_sum_proof_bench_name, |b| { + b.iter_batched( + || { + Halo2Circuit::>::new::( + 17, + halo2_circuit.clone(), + ) + }, + |circuit| { + let mut transcript = Keccak256Transcript::default(); + + Pb::prove(&pp, &circuit, &mut transcript, std_rng()).unwrap(); + transcript.into_proof(); + }, + criterion::BatchSize::SmallInput, // Choose an appropriate batch size + ) + }); +} + +fn criterion_benchmark(_c: &mut Criterion) { + const N_CURRENCIES: usize = 2; + + { + const K: u32 = 17; + const N_USERS: usize = 1 << 16 as usize; + bench_summa::(); + } +} + +pub fn seeded_std_rng() -> impl RngCore + CryptoRng { + StdRng::seed_from_u64(OsRng.next_u64()) +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/prover/bin/commitment_solidity_calldata.json b/prover/bin/commitment_solidity_calldata.json deleted file mode 100644 index 1ae19c41..00000000 --- a/prover/bin/commitment_solidity_calldata.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "range_check_snark_proof": "0x1b200581ce1ccff3f92e35dddd962cbda546c1c03834ca56296e567de16461a4075d4eb1bcbb18879d8c84f3804c11e920660ae1c62e0acb20e476c903ae0a3a261b66db77d711fd90671890321022121affeaf8353d696bf4597a6d9fba617c1560b42a43ed84a13785aa23e8d95a604d7aed90b8a4dd41c15284ac81189b812d536e6e7be13957f2eb82d0ced26c44b76e3dee0b896af61f57575935a346871fb31cc9f50e9d5084bb0d2856c98aa13718b511415ecad0e00bbf66c8f6d90009b068aa48cacfb89f98f17d513735930d7a9ca7c72f5c47ca044d5f145a16721a3cd8678d4ff1328601f5246e8fdfa240975ca59d6553add481f1647dcef2a71f250fb136e25a6ac0884fc15417d2cc436a3b9fc7c57f1f4bd0353ea1249f411f7c76d365074a7c695d59edd2a7c5b9e1d9d2f1f851a3495ebbbcdf88a7e74d2cc291aad02f0ce6e69aac34cb88d35bb2f35f56f873060f47b840745d64ef950cde7ea63d577bbc926c6ebb9b10f3ba1082e6d0c17977c3dda4a9f4212f8a22000f603776df9e725b18eac4a405bd18a56cfe291e84c9b3ef90d7192d1d8b78027de76238369cc7e8759784685b5c0fb08a0a52058dcec38e4d67b64072636414b5494d7838057eb66259bb5c984e864a8b604d96d35790a7e079cc152679241cf6d45a7166853135d1ca333727e8b2353eb7e90ae8391783731d392a79063e28d451e54b553700b3a5d8f6b4fb2c069440b4e26d748d6a425b770433a47c6b03181db50c65bfcb472b070c9353228023f3766f536bc953b8c0b2ed54a879242874e7d166e7573897e65ffb943ee855df1a131f86c18da6126f551dc7e1ae192a693fae10d79f0d9d119b145871e6a6fc1143cd5b53f90a48f849727b79fab93048e2f14f00c297ade3227b32a5f2d19145d0c5c9f7ace1bef44481525a227e1f041a4fb26e18d77036ace80d4d29959a5654893185d6c6e9c1a66dcb0b874b007eeef5091b519b8e16e5877b0746d4bff497fa3022d30675d981ce513bed8628e0f67d71b6eea2c0047b1ef4b85a3ac0bf0462abc518a82ecc900f3f32ce6a21f30533df9e36688b94d1ff7c51f5530a36962556c9ec526fda390a6dec8f0502819520ddcc9722ef50731fdd0698e91d53764a0929bed7d7aab2246d287b612baf952b31fae1fd4270034332ed893d7d0ab181f7d9a68205570b60f99cfd19147ba2d8a835fae9f72a43c9db4c9a5dd3e0060fc69af8a1ec14da5c170eb12316c4f940985d6d3133f36b14e6da6ea88bacf4f26641cddf3a0a540bfe4198e2275b31cb08b7e45baadde23fb64b9bbc95e713fc1b55396a150e75b0038837c40d69af90e6144f5e7c0f2b12349f8a0acf52e21a8219aafe765d9d2f7724425a28e8c9e850b2b52a59a87ede18618b6aa8a10eac03a536e1b996767e0583839b11608307bfc8a7048e7069fe123e06ee9f72c2dcdb3c94d135f8a8f95bca6efb29a5ea36536bf72bb3039e04baddac9f49b8b46cabf9902f828b5a70416a4017005f6933903f821274efad4634fcc2ed4da97e43e6ca1eb07197920066f7d7bb115909765a3e1ea151a31f01c63e7930647424be324d3dc45458237194c38e1e1ffb93985978172ee13e425b627f9800c3eeb1a230540a67ad8d699d02227636029c959c26b504774a84ec7d2e64d7ad3f892f94c4fae8abb26935f2f2006b832af8d3a66febdcc3e5659fd28ff59ada6c7ae44f565e10e6f0a074d86402c6b4176c4853110edae31ee186904261ca3fb3794ac42f8a229422b0099486dc6e5f04314e7ec83fd1e051b33299b14c75ac2b2f5996b4ab0467c40d7978ea2c718d005dfc20f5a84b7b669ae47a3f8dc359417c62745a598ea53308377552579dea12f44b1f03372e42eb71af3e464148d4446b1c6768fc1eea18a20a7ac48d41b12cd41e17891dccaf592009218490a38c9a7b3596aa6ab9ecf4bfffce31eb125e2f339daf6e57f4093b6494784831c8846e0fe84536802805e273cbe14d8531dc12ef4ab51059fc94d959899a25ae31bcd868fca678ab710be698014ff31eee271a23055aa10c35cee8c5b9f6dc3e6277dc8742ab9db7049827e1dfa16be2d0f410e037716dd68a33493c79211c18755892db6d6a279405af7198af9e645d618724d3a287384bcd7bda940d5bfa11abde37d1e0adde6ab114aed31a05d9f2ef3924003f4918f100ddf49def61a1fc3362ddc863ef0c47edfa88444eb7e9912d9c01651316d0b3a50ae36c01955898e0533f18da2bca239959cf058a230c5ec8ad215a0df35d515b250ce2dcc58e738698d8f4ed6b4119fa04b5f224b581b2caa008a111bc65c68ad917ee74c11c57bd93414133c4f856d38d0196f26a686052b92bc59d15f547cab99b15904b5333d5d36a34bce08c8f1d0c88624d294a77d2b707e27dff709dcaa80aa6355b832e6fe4ea8492ca325551707b10f9e5bc5aab64092cd1c0fef6f4165a26c20f5c5d014432b3163fce63b2edfa62a260a40172182a928b6b21e05186bc2191cfb9862ebd6f1352ad66f1074c8f7daf06a4e3d777236e6efe6a555655996d7c1126607f9745d2c0d5466a2a5c83b7cee5ab324b0923e67df7d3799436d4435112ddd5c0abaf53d9fc2fc47734e0fd47b77e1f94ca29a14c3cc78915b9e0628c61b7d677faf49be039084d6db04afb75d5eea151cd2d21d59bc86e914bd9b3c98aff084c09fcac9b1290c5cca92f9771ca41ebbed40709fc41153455c8d86753e9752e34c29060148f8704607a6c3bd3dfddf6ceb72435f3ef8ca862b6eaae98b2fe29b51475cca9179ee06f542a044aa1e3e9d1ed1ff1f31fd1450f557ef56cb8dfe6620fe0aa7b9562e9faf479964d17c877834604ad3fe40204e4fe18ff27388a35200e07faaa9487b50d2b0afe02ffcf0ed6522f9d1d256ce6c89af49420fb379fd793c5e87a01c6541412ed0f348681c03c630b90a0e829e5c873ce97b70fe4f33aab122796c833a9e8aa15f81cc0f9d524e11ff88113a2e0325ab73455dd950276848d9f85aba0006a362c2f963cb473ba401af97c4e4d1bf6c9f70a194b41f27a145c8b69fc045953ae04296ec52bcd3b6e260d3a53f50d1f20c07f1200e2637fa545d1390ebd812771b9bebd6bb189e3990257ccaf91e84f211af01b415fb8d7d493a304cfb03824ff680b22f8ae609d621164ef9d70d88f64c9c48ef3265fdc81cd72940aa59a63c06fa63e79c74e5f2d00ce48d62a3536299dde64df718796e7425826cc487fdb1f179c61edeaf040280aa100f302519c2042d64cca4138eec8b33729f5dfc0a03e795d7cf570a8045e1eff836baf5f06c6c61cca266e976ea0eb122b5e6bd29f3c240645c5c2404e2513eb2b331f3802856bc83bbdc40a64ba6065d4a82663ac87dc08a6bc93e39e2f2767f750e2eab6e88032e0199cb35733e6ac0d17534cd413bab641f8a75534cf049faf9192f6b83cb439f5c5572aea5ce5d581371d4116f1c43ad60a1e3f163f2e15f81ab9597985951f0f063f86976b1077bbcefdf1e4d7fa477fdcc1e7d1390e260f969e8e2c7376b72fa5401ef62d30c409a2d7d579a8eb39c763c2fd84d121771983521ae3de3ad954507938271080cbf83231efb45e28c82d0cb47f1e88162e663c0d8a75e673f4b0e9d9aea6d2f82aa8c6204a695c7bf1b0f7a5bf46772faa8fb8a6e36ed22763eebf1427dd5a8c1da1bdd8fd14eca9d9e65601454ba4082a17f58d273c30f931af7885a25e8e4f2baa9f85dcc970f3cc97c946df591f09b78b7da9db60a8c54e6e1f6a030f1be20bef6e22d747c25e0d268ed3d9f93715b2a618cce6b02161dc00858ce2233068f3c83053eddb805596bd4c58466e96209f7299fdffeca7ff573e2fa41d5b8655626421145f467f05451ac19334b4260a0f443cd9704c549d8d4d96b2a1219ea4e66daec875bfd74f4bb0712e6ac5b22f6ff8564c9bb0907283b79e1dc87b48641d166c40c4e5448d4e8a84c20f120e1da1487aa706d72e4e205c36815c47675754b52b41e51fb237ae36274d12de2121ed49ec2a3cbc8ac40166687bf18acdf75e062b826b25050ebc62f402cbb21820b774f663dea6af4868efa2181eed9dc9321365a104dbe16d01ae67bcb80fe10428abe1a98b038c25a0e9fc54fec9c120a1eff63de904e6306bbfa99b6ee9ba18881a5354469eeb4feef89fa682dcdee62a33757a61d8efdde248a005442cc6247f38fe393a44f0812814b7be1f7d5ee0975060aa82a9e78602419eb5a8f6610723b52608263605d5dff29dbc80d514a99f3d0a9d4dacb07817995102047f1d29347b1317934162c2fd55c39831119eb40fa67e6f7e326fa1fa61122ceeca05144db4355935cb1d1762842b1f1e40423813cfd82113914c83966ad8486ddfcd1fe2390b2d01794e522a4c95d6483661bc24af467c5915ab1a5bf315cc7a2abb08627f170ee896b9015162a8a9d741847ed80e2848af9d632682dee79b61de361c0ba9d2513c8aa794495b3123989c10343db49ad6786f1716dde66d811974890806eea7d70f5154dba13a45816639d2c2dc2b17b6c0b3710c7deeded162de6e0c2f4b9f600209591d33208fd26e8d8c525b6f03931fc714c451b8c40d38f69d04694df2f4a14cbd76f97351c41d940c12dbc04ed654d8cf62f44afdf43dca752191c47a3cf7d2f3932c94a294538bbd2262dd65e25720de90e8f0db604192d1100da03880dbb08234529a77695c7fa3ca1b7cbbd1c347dbb0558dae5ef439ba1917cfa948c1c509f9a7e2ef3ba9d78503975d769c1934b78c741c74fc36c7a106c6942af654bbae1ddfeee473492411ea6d23f7094d280c83869a00ecda054c1992416c6808c8941b3407c22fceb6800eb8b1da9e78b4af5ed9b80af86e2351049341e779893782438dd60920e6ea219aa20cb9189855f6e410548ff582511c1a7e25ef38919457e8e23d8e90f594c68816968ffd8d4fb39aa99467fb149ed529bbe7879d39b284bf9f009b71720f426a566c81848f7bbcbcbf37061e06357c2ee53ecdab1453c7cce77e2c06972e04825d2e4336b95a5609cb08fb693638910269a4f72095076b7d46dc24743fe951485d751282d0418cabeb16ac50444d861a27552c4d6b349fe034be3fc2e35087013ef76f871845ede39ba92386b08a6a0bf6b447d95e05ad65ba15a0b1a636b1a41d6b94fddede61528842ada317b4711bcc372e891ed3cc68634ee0ddad9bbd5c2fcf0ff74cbea665414f482faaeeae09383bfb526a0c9c18a80e93f2a9440a0c398ca9548d39f1ed352d464f0809ca0dba2e2521de785c977c7979c43269fd71ec56b9afae58cf35cc465fc88e168b15e2460234bf5b91183032f4dd8c3aa15d582fa1d17bb55e446292e68565a10a024a7bb44dc8ab203969ff6f5d2b1e2a7e208de5106350fa21ec5246ac5d20e40df1f8439af5f86a6002199b9082f878e7286c1071c6588341de511fac571f5513f7c058dfc614b4f570de2a62614351ea3e664e8971a7e5d63004c9026dd400052a97f9b59d3de75552b7185b5912be32f9a49cbb5cb8f3b716c4137911bdb006bc52868e283baca4692ba389032bfe9d0a700e2f47c14a104a4ea731cabc9e23a3dff6c06ceac32421283e96970dae4f22dc3848d3834f675bbda5ba3a436618b97e5277db6e1cf10d7eb5a49f0540dcf50fc9e469957df24d69a9e790eed20f18d2e8f8d535a388019d6ea8197fe373f663819fb47255677e5585892fc4d20859f6834baf37ac4d9989960790fdf08e0989859b76196fffcff9ab80e3df3905fabb664473c9476f71bd5ef2621ed47f76d076a3ff0fe27777073243b68eeb2a14ab9c57dd4fcf758b03a35f49da50238a7c0a464dd73823abe97ea44a97bc2bbec4ca8ae8bed8200bb2da0e2fca94839b3a7cd06c3f8a7fe341e2b1194ddf23b92500bc858bcf7365a1b4ea53bec3beef3ee71f41c148cd4c382b5e48cd9c16fac06e418ec1af458c8f5b658cc117893d685826985759c1500b28137461c00fc713188ce3264701d7376f588240430bc2a3a441cd811d77218385336781e01958b3b3e68c741d9a15e5ec4d4f591d0341f6270b7ebc262e0e4507c33a73442f8279c5d8f1a3fa68b892e74931532df4d030c30e728d32e9d3e364f578c89710d858432377e59e820ccd54fcef1fe1558a09d96c6758d425b20d61020dbcdf12fb55d12da9804179e37b5eb23de9077b73f10a4de909183782a36b65ec92442930f98bd428540c05622b2a545465c000bbd9b4e70f6f9faaf5af85730e7dd203ab945c07893c6096a8b2f457d092153b54369f007997883cc4430775a70d1718241c395063816dce07ea10d4baba9884b568382b7c0efd47d95d21f8d815441a978863e211e1611841e43049ff989aa3595e64052b448f633be2b2f5c1614227d9a49cf7c6f1b53c0aad1ac041d5c734fc3f2ca2830bd6886250ccb3031747251504c8850d9b3845a76b7b77e0cedd57694098b25b30aa62d26be5f435c7ae2404c804e3805870acea4b76fc9e08a2805549b478b9e9cc3379225fb40e755d10acb7167d639d02fc954d7dfb940d8f23320026967a5eaee125318b5d53046b27d81d57642b283e33b631c8d3f8d36ba43daa3ed16a793d3f5d78afefa136d02d76c7efef3836f37ef3318b0ef2b03a6e76151ba5bf4ceef026d6fae19b369a0cb3cc3debd9e28c13999fb73d6e6913064ce706f066b3735eb9b33c7ff59752164f50f5a2274c3f2abf4e499ec60a0c365c8d00d28909b9b032deeae5fb4b0904cdd16690c9631a25828559ab5d2ff25de31fc6cd68c5f474dcf1f99a8c6c770b20baf5752cc4937046638161fafe364b8d3e2ff83024540a0c1794346e27221b4d0fb61d725325f48465ddc9250922e8784b6740fe9e3e594ff29d84a6e18b0f5c9f0895d79912e990bfbf032e29717962423ef29e5d301e7f6df98b302ef811fe513641dc7844134461fe40bd7122588ee3b5ed9bfe78ea04e4ea585eef2d248d9a64528b632f0a5e570c242dc3188c8b3cc536c7e6248fbf74e28be9baf810f6fec952208765498c1fad4de6bb42a2a60d4eb5f84c76357fb527777f320805a00fe719cad11599aa48c6ea066a8818cfe25ca6041ce3de19e319b48ef7bc30395f7ca65c24d6c6a898742cd1ed8858bf4a3f1e8d0ff948351b860768f8b52440e6f08ce61f0c72d813d09eafb2e702ee1b5a70acbd1c5dd6d06ea2d125af13e9c56d652434e16633d851b80969521d4e32e209a0caedc6b8422cf4f0c57f1a809e252787f9f6d88f9f60273268286b3d5e4ddfb534fae863dd381ef919152b9a220f12b3890b1e1a312919e9776a292c3b4bac2ff35b180d5d83232321b60d9dc75397d11aaa6d151a96028edd8060d23c3b3bd15d179e113a10b14eff8a1f27bfae91aa88a9fa6d7243244e1c1c77bbe9b28bdfd0ebcf0f0eb79b99771b0c02446010ee5bdff5d215283109f54fab077adf59a5961d48105b5c95402f3129d7b10968df0858e798858e96acacc3ba49e02dd8afaafbc45ebd0a89363365", - "grand_sums_batch_proof": "0x17e2032176f6575e95aa4d9d97293edf675fd8aad89e76d99883b4a830564e7d2ca14616b46c35c4573a4e5806a7fde693b0da39ca285023e93c2e3ee781b78b18c815403ccb3ac8188e4a1b761df4504068402c880e4a687311455818ed4ca32367d0768c54895acb9875b2b2f60d85102d455cc28f0d9d2af67ecaa4ac662f", - "total_balances": [ - "0x87f3e", - "0x87f3e" - ] -} \ No newline at end of file diff --git a/prover/bin/gen_commit_and_proofs.rs b/prover/bin/gen_commit_and_proofs.rs deleted file mode 100644 index 4d65d74e..00000000 --- a/prover/bin/gen_commit_and_proofs.rs +++ /dev/null @@ -1,246 +0,0 @@ -#![feature(generic_const_exprs)] -use ethers::types::U256; -use halo2_proofs::{ - arithmetic::Field, - halo2curves::{ - bn256::{Bn256, Fr as Fp, G1Affine, G2Affine}, - group::{cofactor::CofactorCurveAffine, Curve}, - }, - poly::kzg::commitment::KZGCommitmentScheme, - transcript::TranscriptRead, -}; -use halo2_solidity_verifier::Keccak256Transcript; -use num_bigint::BigUint; -use serde::{Deserialize, Serialize}; -use serde_json::to_string_pretty; -use std::{fs::File, io::Write}; -use summa_solvency::{ - circuits::{ - univariate_grand_sum::{UnivariateGrandSum, UnivariateGrandSumConfig}, - utils::{full_prover, full_verifier, generate_setup_artifacts}, - }, - cryptocurrency::Cryptocurrency, - entry::Entry, - utils::{ - amortized_kzg::{create_naive_kzg_proof, verify_kzg_proof}, - big_uint_to_fp, parse_csv_to_entries, - }, -}; - -const K: u32 = 17; -const N_CURRENCIES: usize = 2; -const N_USERS: usize = 16; - -#[derive(Serialize, Deserialize)] -struct CommitmentSolidityCallData { - range_check_snark_proof: String, - grand_sums_batch_proof: String, - total_balances: Vec, -} - -#[derive(Serialize, Deserialize)] -struct InclusionProofCallData { - proof: String, - challenges: Vec, - user_id: String, - user_values: Vec, -} - -fn main() { - // Initialize with entries - let mut entries: Vec> = vec![Entry::init_empty(); N_USERS]; - let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES]; - - // Parse CSV to update entries and cryptos arrays - parse_csv_to_entries::<&str, N_CURRENCIES>("../csv/entry_16.csv", &mut entries, &mut cryptos) - .unwrap(); - - let univariate_grand_sum_circuit = UnivariateGrandSum::< - N_USERS, - N_CURRENCIES, - UnivariateGrandSumConfig, - >::init(entries.to_vec()); - - let (params, pk, _) = generate_setup_artifacts( - K, - Some("../backend/ptau/hermez-raw-17"), - &univariate_grand_sum_circuit, - ) - .unwrap(); - - // Create a proof - let instances = vec![Fp::zero(); 1]; // This instance is necessary to verify proof on solidity verifier. - let (zk_snark_proof, advice_polys, omega) = full_prover( - ¶ms, - &pk, - univariate_grand_sum_circuit.clone(), - &[instances.clone()], - ); - - // Verify the proof to ensure validity - assert!(full_verifier( - ¶ms, - pk.get_vk(), - &zk_snark_proof, - &[instances] - )); - - let challenge = Fp::zero(); - let mut csv_total: Vec = vec![BigUint::from(0u32); N_CURRENCIES]; - for entry in &entries { - for (i, balance) in entry.balances().iter().enumerate() { - csv_total[i] += balance; - } - } - - // Evaluate the commitments from the snark proof - let mut kzg_commitments = Vec::with_capacity(N_CURRENCIES); - let mut transcript = Keccak256Transcript::new(zk_snark_proof.as_slice()); - for _ in 0..(N_CURRENCIES + 1) { - let point: G1Affine = transcript.read_point().unwrap(); - kzg_commitments.push(point.to_curve()); - } - - let poly_length = 1 << u64::from(K); - let total_balances = csv_total - .iter() - .map(|x| big_uint_to_fp(x) * Fp::from(poly_length).invert().unwrap()) - .collect::>(); - - let mut grand_sums_kzg_proof = Vec::new(); - for balance_column in 1..(N_CURRENCIES + 1) { - let f_poly = advice_polys.advice_polys.get(balance_column).unwrap(); - - let currency_index = balance_column - 1; - let kzg_proof = create_naive_kzg_proof::>( - ¶ms, - pk.get_vk().get_domain(), - f_poly, - challenge, - total_balances[currency_index], - ); - - // Ensure the KZG proof is valid - assert!(verify_kzg_proof( - ¶ms, - kzg_commitments[balance_column], - kzg_proof, - &challenge, - &total_balances[currency_index], - )); - - // Convert to affine point and serialize to bytes - let kzg_proof_affine = kzg_proof.to_affine(); - let mut kzg_proof_affine_x = kzg_proof_affine.x.to_bytes(); - let mut kzg_proof_affine_y = kzg_proof_affine.y.to_bytes(); - kzg_proof_affine_x.reverse(); - kzg_proof_affine_y.reverse(); - - // Concatenate x and y of the KZG proof - grand_sums_kzg_proof.push([kzg_proof_affine_x, kzg_proof_affine_y].concat()); - } - - let commitment = CommitmentSolidityCallData { - range_check_snark_proof: format!("0x{}", hex::encode(zk_snark_proof)), - grand_sums_batch_proof: format!("0x{}", hex::encode(grand_sums_kzg_proof.concat())), - total_balances: csv_total - .iter() - .map(|x| U256::from_little_endian(big_uint_to_fp(x).to_bytes().as_slice())) - .collect::>(), - }; - - // Serialize the data for solidity - let serialized_data = to_string_pretty(&commitment).expect("Failed to serialize data"); - - // Save the serialized data to a JSON file - let mut file = - File::create("./bin/commitment_solidity_calldata.json").expect("Unable to create file"); - file.write_all(serialized_data.as_bytes()) - .expect("Unable to write data to file"); - - // For testing, open user balances and generate a proof for a specific user index - let user_index = 1_u16; // Example user index for proof generation - let challenge = omega.pow_vartime([user_index as u64]); - - let user_values = &entries - .get(user_index as usize) - .map(|entry| { - std::iter::once(big_uint_to_fp(entry.username_as_big_uint())) - .chain(entry.balances().iter().map(big_uint_to_fp)) - .collect::>() - }) - .unwrap(); - - let column_range = 0..N_CURRENCIES + 1; - let mut inclusion_proof: Vec> = Vec::new(); - for column_index in column_range { - let f_poly = advice_polys.advice_polys.get(column_index).unwrap(); - - let z = if column_index == 0 { - big_uint_to_fp(entries[user_index as usize].username_as_big_uint()) - } else { - big_uint_to_fp(&entries[user_index as usize].balances()[column_index - 1]) - }; - - let kzg_proof = create_naive_kzg_proof::>( - ¶ms, - pk.get_vk().get_domain(), - f_poly, - challenge, - z, - ); - - assert!( - verify_kzg_proof( - ¶ms, - kzg_commitments[column_index], - kzg_proof, - &challenge, - &z, - ), - "KZG proof verification failed for user {}", - user_index - ); - - // Convert to affine point and serialize to bytes - let kzg_proof_affine = kzg_proof.to_affine(); - let mut kzg_proof_affine_x = kzg_proof_affine.x.to_bytes(); - let mut kzg_proof_affine_y = kzg_proof_affine.y.to_bytes(); - kzg_proof_affine_x.reverse(); - kzg_proof_affine_y.reverse(); - - // Concat x, y of kzg_proof - inclusion_proof.push([kzg_proof_affine_x, kzg_proof_affine_y].concat()); - } - - let user_values = user_values - .iter() - .map(|x| U256::from_little_endian(x.to_bytes().as_slice())) - .collect::>(); - - // Evaluate S_G2 points with challenge for verifying proof on the KZG solidity verifier - let s_g2 = -params.s_g2() + (G2Affine::generator() * challenge); - let s_g2_affine = s_g2.to_affine(); - - let challenges = vec![ - U256::from_little_endian(s_g2_affine.x.c1.to_bytes().as_slice()), - U256::from_little_endian(s_g2_affine.x.c0.to_bytes().as_slice()), - U256::from_little_endian(s_g2_affine.y.c1.to_bytes().as_slice()), - U256::from_little_endian(s_g2_affine.y.c0.to_bytes().as_slice()), - ]; - - let data = InclusionProofCallData { - proof: format!("0x{}", hex::encode(inclusion_proof.concat())), - user_id: entries[user_index as usize].username().to_string(), - challenges, - user_values, - }; - - let serialized_data = to_string_pretty(&data).expect("Failed to serialize data"); - - // Save the serialized data to a JSON file - let mut file = File::create("./bin/inclusion_proof_solidity_calldata.json") - .expect("Unable to create file"); - file.write_all(serialized_data.as_bytes()) - .expect("Unable to write data to file"); -} diff --git a/prover/bin/gen_verifier.rs b/prover/bin/gen_verifier.rs deleted file mode 100644 index ea0c5810..00000000 --- a/prover/bin/gen_verifier.rs +++ /dev/null @@ -1,147 +0,0 @@ -#![feature(generic_const_exprs)] -use halo2_proofs::{ - halo2curves::bn256::Fr as Fp, - poly::kzg::{ - multiopen::{ProverSHPLONK, VerifierSHPLONK}, - strategy::SingleStrategy, - }, - transcript::TranscriptWriterBuffer, -}; -use halo2_solidity_verifier::{ - compile_solidity, encode_calldata, BatchOpenScheme::Bdfg21, Evm, Keccak256Transcript, - SolidityGenerator, -}; -use prelude::*; -use rand::rngs::OsRng; -use summa_solvency::{ - circuits::{ - univariate_grand_sum::{UnivariateGrandSum, UnivariateGrandSumConfig}, - utils::generate_setup_artifacts, - }, - cryptocurrency::Cryptocurrency, - entry::Entry, - utils::parse_csv_to_entries, -}; - -const K: u32 = 17; -const N_CURRENCIES: usize = 2; -const N_USERS: usize = 16; - -fn main() { - // In order to generate the verifier we create the circuit using the init_empty() method, which means that the circuit is not initialized with any data. - let circuit = UnivariateGrandSum::< - N_USERS, - N_CURRENCIES, - UnivariateGrandSumConfig, - >::init_empty(); - - let (params, pk, _) = - generate_setup_artifacts(K, Some("../backend/ptau/hermez-raw-17"), &circuit).unwrap(); - - // Only now we can instantiate the circuit with the actual inputs - let mut entries: Vec> = vec![Entry::init_empty(); N_USERS]; - let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES]; - - parse_csv_to_entries::<&str, N_CURRENCIES>("../csv/entry_16.csv", &mut entries, &mut cryptos) - .unwrap(); - - let univariate_grand_sum_circuit = UnivariateGrandSum::< - N_USERS, - N_CURRENCIES, - UnivariateGrandSumConfig, - >::init(entries.to_vec()); - - // 1. Generate Snark Verifier Contract and Verification Key - // - // the instance value is not used in proving, but it is necessary to SolidityGenerator and it should at least 1. - let num_instance = 1_usize; - let generator: SolidityGenerator<'_> = - SolidityGenerator::new(¶ms, pk.get_vk(), Bdfg21, num_instance); - let (verifier_solidity, vk_verifier) = generator.render_separately().unwrap(); - - let verifier_solidity_fixed = verifier_solidity - .replace("Halo2Verifier", "Verifier") - .replace(") public returns (bool)", ") public view returns (bool)"); - - let verifier_code = compile_solidity(&verifier_solidity_fixed); - let vk_code = compile_solidity(&vk_verifier); - - // 2. Generate Snark Proof for range check - // - // the instance values has to be at least more than one due to verifier contract that generated from SolidityGenerator. - let instances: Vec = vec![Fp::zero(); 1]; - let mut transcript = Keccak256Transcript::new(Vec::new()); - - let result = create_proof::<_, ProverSHPLONK<_>, _, _, _, _>( - ¶ms, - &pk, - &[univariate_grand_sum_circuit], - &[&[&instances]], - &mut OsRng, - &mut transcript, - ); - assert!(result.is_ok()); - - let result_unwrapped = result.unwrap(); - result_unwrapped.0.expect("prover should not fail"); - - let zk_snark_proof = transcript.finalize(); - - // Check verification on verifier function - let verified = { - let mut transcript = Keccak256Transcript::new(zk_snark_proof.as_slice()); - verify_proof::<_, VerifierSHPLONK<_>, _, _, _>( - ¶ms, - pk.get_vk(), - SingleStrategy::new(¶ms), - &[&[&instances]], - &mut transcript, - ) - }; - assert!(verified.is_ok()); - - // 3. Deploy Snark Verifier Contract and verify snark proof - let mut evm = Evm::default(); - - // Calldata for verifying proof on evm - let vk_address = evm.create(vk_code); - let proof_calldata = encode_calldata(Some(vk_address.into()), &zk_snark_proof, &instances); - - // Initiate verifier contract - let verifier_address = evm.create(verifier_code); - let (_, output) = evm.call(verifier_address, proof_calldata); - - // If successfuly verified, the verifier contract will return 1. - assert_eq!(output, [vec![0; 31], vec![1]].concat()); - save_solidity("SnarkVerifier.sol", &verifier_solidity_fixed); - save_solidity("VerifyingKey.sol", &vk_verifier); -} - -fn save_solidity(name: impl AsRef, solidity: &str) { - File::create(format!("../contracts/src/{}", name.as_ref())) - .unwrap() - .write_all(solidity.as_bytes()) - .unwrap(); -} - -mod prelude { - pub use halo2_proofs::{ - circuit::{Layouter, SimpleFloorPlanner, Value}, - halo2curves::{ - bn256::{Bn256, Fr, G1Affine}, - ff::PrimeField, - }, - plonk::*, - poly::{commitment::Params, kzg::commitment::ParamsKZG, Rotation}, - }; - pub use rand::{ - rngs::{OsRng, StdRng}, - RngCore, SeedableRng, - }; - pub use std::{ - collections::HashMap, - fs::{create_dir_all, File}, - io::Write, - ops::Range, - }; -} diff --git a/prover/bin/inclusion_proof_solidity_calldata.json b/prover/bin/inclusion_proof_solidity_calldata.json deleted file mode 100644 index 92130cc1..00000000 --- a/prover/bin/inclusion_proof_solidity_calldata.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "proof": "0x0faaa8aa92bf36e2601bdd9d5be92bb5c7aa6f982661cff0611d0bd8ccccb9bd171586516226f99958cdb181eecdfb1ce9bd48e5ae3c19aea353c163c7acf1db0938c672375247acf7a110224e1f3d0e118b289a02c8b4a0acd33a8d209dbebc01895e90be59da66f1de8e8a144047936e7393e312fbbcfe11960be9de661277150f79ec188c492fc71556342c001c2cdf89aca2df24b2f68514e1742185c2021f0479d9e8e1a3e1c14e2bac6af1c5ebd3d6c5b35c230c0cc92c554cc245a9d5", - "challenges": [ - "0xf79a0045992596e3278606b5317aaf4f6bb65071219b1c89d542509fe6dddd3", - "0x2299faaf0e21893e99005dc9165fba869b5aa88bcac5af4395071fd569686fde", - "0x2480ccf8a3834d03badc6b0c35773d758908019658fe9ea3bf85dc202257cfda", - "0x2bd763bd08804bb437e62575eff584497632e3d3034a20f2a868b1136e4adb6e" - ], - "user_id": "MBlfbBGI", - "user_values": [ - "0x4d426c6662424749", - "0x108ef", - "0x48db" - ] -} \ No newline at end of file diff --git a/prover/examples/chunked_univariate_grand_sum.rs b/prover/examples/chunked_univariate_grand_sum.rs deleted file mode 100644 index 4ca6dc99..00000000 --- a/prover/examples/chunked_univariate_grand_sum.rs +++ /dev/null @@ -1,178 +0,0 @@ -#![feature(generic_const_exprs)] -use std::error::Error; - -use halo2_proofs::halo2curves::bn256::{Fr as Fp, G1Affine}; -use halo2_proofs::halo2curves::group::Curve; -use halo2_proofs::transcript::TranscriptRead; -use halo2_proofs::{ - arithmetic::Field, halo2curves::bn256::Bn256, poly::kzg::commitment::KZGCommitmentScheme, -}; -use halo2_solidity_verifier::Keccak256Transcript; -use num_bigint::BigUint; - -use summa_solvency::circuits::utils::generate_setup_artifacts; -use summa_solvency::{ - circuits::{ - univariate_grand_sum::{NoRangeCheckConfig, UnivariateGrandSum}, - utils::full_prover, - }, - cryptocurrency::Cryptocurrency, - entry::Entry, - utils::{ - amortized_kzg::{commit_kzg, create_naive_kzg_proof, verify_kzg_proof}, - big_uint_to_fp, parse_csv_to_entries, - }, -}; - -const K: u32 = 9; -const N_CURRENCIES: usize = 2; -const N_USERS_TOTAL: usize = 64; -const N_USERS_CHUNK: usize = N_USERS_TOTAL / 2; - -fn main() -> Result<(), Box> { - let path = "../csv/entry_64.csv"; - - let mut entries: Vec> = vec![Entry::init_empty(); N_USERS_TOTAL]; - let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES]; - - parse_csv_to_entries::<&str, N_CURRENCIES>(path, &mut entries, &mut cryptos).unwrap(); - - // Calculate total for all balance entries - let mut csv_total: Vec = vec![BigUint::from(0u32); N_CURRENCIES]; - - for entry in &entries { - for (i, balance) in entry.balances().iter().enumerate() { - csv_total[i] += balance; - } - } - - // Split the user base into two equal chunks of N_USERS_TOTAL/2 each - let entries_first_chunk = entries[0..N_USERS_CHUNK].to_vec(); - // Calculate the total for the first chunk - let mut csv_total_1: Vec = vec![BigUint::from(0u32); N_CURRENCIES]; - for entry in &entries_first_chunk { - for (i, balance) in entry.balances().iter().enumerate() { - csv_total_1[i] += balance; - } - } - let entries_second_chunk = entries[N_USERS_CHUNK..].to_vec(); - // Calculate the total for the second chunk - let mut csv_total_2: Vec = vec![BigUint::from(0u32); N_CURRENCIES]; - for entry in &entries_second_chunk { - for (i, balance) in entry.balances().iter().enumerate() { - csv_total_2[i] += balance; - } - } - // Index of the advice polynomial to be used for the subsequent examples - const BALANCES_INDEX: usize = 1; - assert!( - &csv_total_1[BALANCES_INDEX - 1] + &csv_total_2[BALANCES_INDEX - 1] - == csv_total[BALANCES_INDEX - 1], - "The sum of the chunks' total should be equal to the grand total" - ); - - type CONFIG = NoRangeCheckConfig; - - let circuit_1 = UnivariateGrandSum::::init_empty(); - // Generate the setup artifacts using an empty circuit - let (params, pk, vk) = generate_setup_artifacts(K, None, &circuit_1).unwrap(); - - // Instantiate the actual circuits for the first and second chunk - let circuit_1 = - UnivariateGrandSum::::init(entries_first_chunk); - let circuit_2 = - UnivariateGrandSum::::init(entries_second_chunk); - - // The zkSNARK proofs encode the balances of the first chunk and the second chunk - // in the corresponding advice polynomials - let (proof_1, advice_polys_1, _) = full_prover(¶ms, &pk, circuit_1.clone(), &[vec![]]); - let (proof_2, advice_polys_2, _) = full_prover(¶ms, &pk, circuit_2.clone(), &[vec![]]); - - // Get the BALANCES_INDEX advice polynomial from each chunk - let f_poly_1 = advice_polys_1.advice_polys.get(BALANCES_INDEX).unwrap(); - let f_poly_2 = advice_polys_2.advice_polys.get(BALANCES_INDEX).unwrap(); - - // These advice polynomials can then be used to independently produce the user inclusion KZG proofs. - // This allows to significantly speed up the inclusion proof by using smaller `N_USERS_CHUNK` size - // and parallelizing the proof generation. - - // Take the KZG commitment of each chunk from the zkSNARK proof transcript - let mut transcript_1 = Keccak256Transcript::new(proof_1.as_slice()); - let mut advice_commitments_1 = Vec::new(); - (0..N_CURRENCIES + 1).for_each(|_| { - let point: G1Affine = transcript_1.read_point().unwrap(); - advice_commitments_1.push(point); - }); - let kzg_commitment_1 = advice_commitments_1[BALANCES_INDEX]; - let mut transcript_2 = Keccak256Transcript::new(proof_2.as_slice()); - let mut advice_commitments_2 = Vec::new(); - (0..N_CURRENCIES + 1).for_each(|_| { - let point: G1Affine = transcript_2.read_point().unwrap(); - advice_commitments_2.push(point); - }); - let kzg_commitment_2 = advice_commitments_2[BALANCES_INDEX]; - assert!( - kzg_commitment_1 != kzg_commitment_2, - "Commitments should be different" - ); - - // The homomorphic property of KZG commitments allows us to sum the individual chunk commitments - // to produce the KZG opening proof for the grand total - let kzg_commitment_sum = kzg_commitment_1 + kzg_commitment_2; - - // First, add the polynomials together coefficient-wise - let domain = vk.get_domain(); - let mut f_poly_total = domain.empty_coeff(); - - for (poly, value) in f_poly_total - .iter_mut() - .zip(f_poly_1.iter().zip(f_poly_2.iter())) - { - *poly = *value.0 + *value.1; - } - - // Demonstrating the homomorphic property of KZG commitments. The sum of the KZG commitments - // to the chunk polynomials should be the same as the KZG commitment to the total polynomial - // that is a sum of the chunk polynomials - let kzg_commitment_total = commit_kzg(¶ms, &f_poly_total); - assert!( - kzg_commitment_sum.to_affine() == kzg_commitment_total.to_affine(), - "Commitments should be equal" - ); - - let poly_length = 1 << u64::from(K); - - // We're opening the resulting polynomial at x = 0 and expect the constant coefficient - // to be equal to the grand total divided by the size of the polynomial - // thanks to the univariate grand sum property. - let challenge = Fp::ZERO; - // The expected evaluation of the polynomial at x = 0 is the grand total divided by the size of the polynomial - let eval = - big_uint_to_fp(&(csv_total[BALANCES_INDEX - 1])) * Fp::from(poly_length).invert().unwrap(); - let kzg_proof = create_naive_kzg_proof::>( - ¶ms, - &domain, - &f_poly_total, - challenge, - eval, - ); - - // KZG proof verification demonstrates that we can successfully verify the grand total - // after building the total KZG commitment from the chunk commitments - assert!( - verify_kzg_proof(¶ms, kzg_commitment_sum, kzg_proof, &challenge, &eval), - "KZG proof verification failed" - ); - assert!( - !verify_kzg_proof( - ¶ms, - kzg_commitment_sum, - kzg_proof, - &challenge, - &big_uint_to_fp(&BigUint::from(123u32)), - ), - "Invalid proof verification should fail" - ); - - Ok(()) -} diff --git a/prover/prints/range-check-layout.png b/prover/prints/range-check-layout.png index 736e963f8b5914ac111eda7eaa6a6d04169446b1..579656ef6855d9618fbe5a45f6d4a0cb77afa0cc 100644 GIT binary patch delta 10498 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 Izww9v3(OG1asU7T delta 13105 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 z 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 diff --git a/prover/prints/univariate-grand-sum-layout.png b/prover/prints/summa-hyperplonk-layout.png similarity index 96% rename from prover/prints/univariate-grand-sum-layout.png rename to prover/prints/summa-hyperplonk-layout.png index e9541d1ec1b4d5dd0222c4cd583c9977f48935d4..497b11f35f8a911a864deece366d8c717a15a9d0 100644 GIT binary patch delta 31165 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 Ad;kCd delta 35619 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 4], } -/// Helper chip that verfiies that the element witnessed in a given cell lies within the u64 range. +/// Helper chip that verifies that the element witnessed in a given cell lies within the u64 range. /// For example, Let's say we want to constraint 0x1f2f3f4f5f6f7f8f to be a u64. /// Note that the lookup table `range` is by default loaded with values from 0 to 2^16 - 1. /// `z` is the advice column that contains the element to be checked. @@ -140,7 +140,7 @@ impl RangeCheckU64Chip { .map(|x| decompose_fp_to_byte_pairs(x, 4)) .transpose_vec(4); - // Initalize an empty vector of cells for the truncated right-shifted values of the element to be checked. + // Initialize an empty vector of cells for the truncated right-shifted values of the element to be checked. let mut z = element.clone(); // Calculate 1 / 2^16 diff --git a/prover/src/chips/range/tests.rs b/prover/src/chips/range/tests.rs index 9b826100..f9425443 100644 --- a/prover/src/chips/range/tests.rs +++ b/prover/src/chips/range/tests.rs @@ -153,14 +153,14 @@ impl Circuit for TestCircuit { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - // Initiate the range check chip + // Initialize the range check chip let range_chip = RangeCheckU64Chip::construct(config.range_check_config); // Load the lookup table let range = 1 << 16; layouter.assign_region( - || format!("load range check table of 64 bits"), + || "load range check table of 64 bits".to_string(), |mut region| { for i in 0..range { region.assign_fixed( @@ -174,7 +174,7 @@ impl Circuit for TestCircuit { }, )?; - // Initiate the add chip + // Initialize the add chip let addchip = AddChip::construct(config.addchip_config); let (_, _, c) = addchip.assign(self.a, self.b, layouter.namespace(|| "add chip"))?; @@ -220,7 +220,8 @@ mod testing { let b = Fp::from(1); let circuit = TestCircuit { a, b }; - let prover = MockProver::run(k, &circuit, vec![vec![Fp::zero()]]).unwrap(); + let prover = + MockProver::run::(k, &circuit, vec![vec![Fp::zero()]]).unwrap(); prover.assert_satisfied(); } @@ -238,7 +239,8 @@ mod testing { let b = Fp::from(2); let circuit = TestCircuit { a, b }; - let invalid_prover = MockProver::run(k, &circuit, vec![vec![Fp::zero()]]).unwrap(); + let invalid_prover = + MockProver::run::(k, &circuit, vec![vec![Fp::zero()]]).unwrap(); assert_eq!( invalid_prover.verify(), Err(vec![ @@ -274,7 +276,7 @@ mod testing { b: Fp::from(1), }; halo2_proofs::dev::CircuitLayout::default() - .render(9, &circuit, &root) + .render::(9, &circuit, &root) .unwrap(); } } diff --git a/prover/src/circuits/mod.rs b/prover/src/circuits/mod.rs index bbd1096b..1f44e02c 100644 --- a/prover/src/circuits/mod.rs +++ b/prover/src/circuits/mod.rs @@ -1,3 +1,3 @@ +pub mod summa_circuit; +#[cfg(test)] mod tests; -pub mod univariate_grand_sum; -pub mod utils; diff --git a/prover/src/circuits/summa_circuit.rs b/prover/src/circuits/summa_circuit.rs new file mode 100644 index 00000000..2263e342 --- /dev/null +++ b/prover/src/circuits/summa_circuit.rs @@ -0,0 +1,274 @@ +pub mod summa_hyperplonk { + + use crate::chips::range::range_check::{RangeCheckU64Chip, RangeCheckU64Config}; + use crate::entry::Entry; + use crate::utils::big_uint_to_fp; + use halo2_proofs::arithmetic::Field; + use halo2_proofs::halo2curves::bn256::Fr as Fp; + use halo2_proofs::plonk::{Expression, Selector}; + use halo2_proofs::poly::Rotation; + use halo2_proofs::{ + circuit::{Layouter, SimpleFloorPlanner, Value}, + plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance}, + }; + use num_bigint::BigUint; + use plonkish_backend::frontend::halo2::CircuitExt; + use rand::RngCore; + + #[derive(Clone)] + pub struct SummaConfig { + username: Column, + balances: [Column; N_CURRENCIES], + running_sums: [Column; N_CURRENCIES], + range_check_configs: [RangeCheckU64Config; N_CURRENCIES], + range_u16: Column, + instance: Column, + selector: Selector, + } + + impl SummaConfig { + fn configure(meta: &mut ConstraintSystem, running_sum_selector: &Selector) -> Self { + let username = meta.advice_column(); + + let balances = [(); N_CURRENCIES].map(|_| meta.advice_column()); + let running_sums = [(); N_CURRENCIES].map(|_| meta.advice_column()); + + for column in &running_sums { + meta.enable_equality(*column); + } + + let range_u16 = meta.fixed_column(); + + meta.enable_constant(range_u16); + + meta.annotate_lookup_any_column(range_u16, || "LOOKUP_MAXBITS_RANGE"); + + // Create an empty array of range check configs + let mut range_check_configs = Vec::with_capacity(N_CURRENCIES); + + let instance = meta.instance_column(); + meta.enable_equality(instance); + + for item in balances.iter().take(N_CURRENCIES) { + let z = *item; + // Create 4 advice columns for each range check chip + let zs = [(); 4].map(|_| meta.advice_column()); + + for column in &zs { + meta.enable_equality(*column); + } + + let range_check_config = RangeCheckU64Chip::configure(meta, z, zs, range_u16); + + range_check_configs.push(range_check_config); + } + + meta.create_gate("Running sum gate", |meta| { + let mut running_sum_constraint = vec![]; + let s = meta.query_selector(*running_sum_selector); + for j in 0..N_CURRENCIES { + let prev_running_sum = meta.query_advice(running_sums[j], Rotation::prev()); + let curr_running_sum = meta.query_advice(running_sums[j], Rotation::cur()); + let curr_balance = meta.query_advice(balances[j], Rotation::cur()); + running_sum_constraint.push( + s.clone() + * (curr_running_sum.clone() - prev_running_sum - curr_balance.clone()) + + (Expression::Constant(Fp::ONE) - s.clone()) + * (curr_running_sum - curr_balance), + ) + } + running_sum_constraint + }); + + Self { + username, + balances, + running_sums, + range_check_configs: range_check_configs.try_into().unwrap(), + range_u16, + instance, + selector: *running_sum_selector, + } + } + } + + #[derive(Clone, Default)] + pub struct SummaHyperplonk { + pub entries: Vec>, + pub grand_total: Vec, + } + + impl SummaHyperplonk { + pub fn init(user_entries: Vec>) -> Self { + let mut grand_total = vec![BigUint::from(0u64); N_CURRENCIES]; + for entry in user_entries.iter() { + for (i, balance) in entry.balances().iter().enumerate() { + grand_total[i] += balance; + } + } + + Self { + entries: user_entries, + grand_total, + } + } + } + + impl Circuit + for SummaHyperplonk + { + type Config = SummaConfig; + type FloorPlanner = SimpleFloorPlanner; + + fn without_witnesses(&self) -> Self { + unimplemented!() + } + + fn configure(meta: &mut ConstraintSystem) -> Self::Config { + //TODO what's the meaning of this? + meta.set_minimum_degree(4); + let running_sum_selector = &meta.complex_selector(); + SummaConfig::configure(meta, running_sum_selector) + } + + fn synthesize( + &self, + config: Self::Config, + mut layouter: impl Layouter, + ) -> Result<(), Error> { + // Assign entries + let (assigned_balances, last_running_sums) = layouter + .assign_region( + || "assign user entries", + |mut region| { + // create a bidimensional vector to store the assigned balances. The first dimension is N_USERS, the second dimension is N_CURRENCIES + let mut assigned_balances = vec![]; + + let mut running_sum_values = vec![vec![]]; + let mut last_assigned_running_sums = vec![]; + + for i in 0..N_USERS { + running_sum_values.push(vec![]); + + region.assign_advice( + || "username", + config.username, + i, + || { + Value::known(big_uint_to_fp( + self.entries[i].username_as_big_uint(), + )) + }, + )?; + + let mut assigned_balances_row = vec![]; + + for (j, balance) in self.entries[i].balances().iter().enumerate() { + let balance_value = Value::known(big_uint_to_fp(balance)); + + let assigned_balance = region.assign_advice( + || format!("balance {}", j), + config.balances[j], + i, + || balance_value, + )?; + + assigned_balances_row.push(assigned_balance); + + let prev_running_sum_value = if i == 0 { + Value::known(Fp::ZERO) + } else { + running_sum_values[i - 1][j] + }; + + running_sum_values[i].push(prev_running_sum_value + balance_value); + + let assigned_running_sum = region.assign_advice( + || format!("running sum {}", j), + config.running_sums[j], + i, + || running_sum_values[i][j], + )?; + + if i == N_USERS - 1 { + last_assigned_running_sums.push(assigned_running_sum); + } + } + + if i > 0 { + config.selector.enable(&mut region, i)?; + } + + assigned_balances.push(assigned_balances_row); + } + + Ok((assigned_balances, last_assigned_running_sums.clone())) + }, + ) + .unwrap(); + + // Initialize the range check chips + let range_check_chips = config + .range_check_configs + .iter() + .map(|config| RangeCheckU64Chip::construct(*config)) + .collect::>(); + + // Load lookup table for range check u64 chip + let range = 1 << 16; + + layouter.assign_region( + || "load range check table of 16 bits".to_string(), + |mut region| { + for i in 0..range { + region.assign_fixed( + || "assign cell in fixed column", + config.range_u16, + i, + || Value::known(Fp::from(i as u64)), + )?; + } + Ok(()) + }, + )?; + + // Perform range check on the assigned balances + for (i, user_balances) in assigned_balances.iter().enumerate().take(N_USERS) { + for (j, balance) in user_balances.iter().enumerate() { + let mut zs = Vec::with_capacity(4); + + layouter.assign_region( + || format!("Perform range check on balance {} of user {}", j, i), + |mut region| { + range_check_chips[j].assign(&mut region, &mut zs, balance)?; + Ok(()) + }, + )?; + + layouter.constrain_instance(zs[3].cell(), config.instance, 0)?; + } + } + + for (i, last_running_sum) in last_running_sums.iter().enumerate().take(N_CURRENCIES) { + layouter.constrain_instance(last_running_sum.cell(), config.instance, 1 + i)?; + } + + Ok(()) + } + } + + impl CircuitExt + for SummaHyperplonk + { + fn rand(_: usize, _: impl RngCore) -> Self { + unimplemented!() + } + + fn instances(&self) -> Vec> { + // The last decomposition of each range check chip should be zero + let mut instances = vec![Fp::ZERO]; + instances.extend(self.grand_total.iter().map(big_uint_to_fp)); + vec![instances] + } + } +} diff --git a/prover/src/circuits/tests.rs b/prover/src/circuits/tests.rs index a2a8867a..ba9c2f24 100644 --- a/prover/src/circuits/tests.rs +++ b/prover/src/circuits/tests.rs @@ -1,556 +1,119 @@ -#[cfg(test)] -mod test { +use plonkish_backend::{ + backend::{hyperplonk::HyperPlonk, PlonkishBackend, PlonkishCircuit, PlonkishCircuitInfo}, + frontend::halo2::Halo2Circuit, + halo2_curves::bn256::{Bn256, Fr as Fp}, + pcs::{multilinear::MultilinearKzg, PolynomialCommitmentScheme}, + util::{ + arithmetic::PrimeField, + transcript::{InMemoryTranscript, Keccak256Transcript, TranscriptRead, TranscriptWrite}, + DeserializeOwned, Serialize, + }, + Error::InvalidSumcheck, +}; +use std::hash::Hash; + +use rand::{ + rngs::{OsRng, StdRng}, + CryptoRng, RngCore, SeedableRng, +}; + +use crate::{ + circuits::summa_circuit::summa_hyperplonk::SummaHyperplonk, utils::generate_dummy_entries, +}; +const K: u32 = 17; +const N_CURRENCIES: usize = 2; +const N_USERS: usize = 1 << 16; + +pub fn run_plonkish_backend( + num_vars: usize, + circuit_fn: impl Fn(usize) -> (PlonkishCircuitInfo, C), +) where + F: PrimeField + Hash + Serialize + DeserializeOwned, + Pb: PlonkishBackend, + T: TranscriptRead<>::CommitmentChunk, F> + + TranscriptWrite<>::CommitmentChunk, F> + + InMemoryTranscript, + C: PlonkishCircuit, +{ + let (circuit_info, circuit) = circuit_fn(num_vars); + let instances = circuit.instances(); + + let param = Pb::setup(&circuit_info, seeded_std_rng()).unwrap(); + + let (pp, vp) = Pb::preprocess(¶m, &circuit_info).unwrap(); + + let proof = { + let mut transcript = T::new(()); + Pb::prove(&pp, &circuit, &mut transcript, seeded_std_rng()).unwrap(); + transcript.into_proof() + }; - use crate::circuits::univariate_grand_sum::{ - CircuitConfig, NoRangeCheckConfig, UnivariateGrandSum, UnivariateGrandSumConfig, + let result = { + let mut transcript = T::from_proof((), proof.as_slice()); + Pb::verify(&vp, instances, &mut transcript, seeded_std_rng()) }; - use crate::circuits::utils::{ - compute_h_parallel, full_prover, full_verifier, generate_setup_artifacts, - open_all_user_points_amortized, open_grand_sums, open_single_user_point_amortized, - open_user_points, verify_grand_sum_openings, verify_user_inclusion, + assert_eq!(result, Ok(())); + + let wrong_instances = instances[0] + .iter() + .map(|instance| *instance + F::ONE) + .collect::>(); + let wrong_result = { + let mut transcript = T::from_proof((), proof.as_slice()); + Pb::verify( + &vp, + &vec![wrong_instances], + &mut transcript, + seeded_std_rng(), + ) }; - use crate::cryptocurrency::Cryptocurrency; - use crate::entry::Entry; - use crate::utils::amortized_kzg::{commit_kzg, create_naive_kzg_proof, verify_kzg_proof}; - use crate::utils::{big_uint_to_fp, parse_csv_to_entries}; - use ark_std::{end_timer, start_timer}; - use halo2_proofs::arithmetic::Field; - use halo2_proofs::dev::{FailureLocation, MockProver, VerifyFailure}; - use halo2_proofs::halo2curves::bn256::{Bn256, Fr as Fp, G1Affine}; - use halo2_proofs::plonk::{Any, ProvingKey, VerifyingKey}; - use halo2_proofs::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; - use num_bigint::BigUint; - use rand::rngs::OsRng; - use rand::Rng; - - const K: u32 = 17; - const N_CURRENCIES: usize = 2; - const N_USERS: usize = 16; - - #[test] - fn test_amortized_kzg() { - let path = "../csv/entry_16.csv"; - - let (entries, circuit, pk, _, params) = - set_up::<9, N_USERS, N_CURRENCIES, NoRangeCheckConfig>(path); - - let (_, advice_polys, omega) = - full_prover(¶ms, &pk, circuit.clone(), &[vec![Fp::zero()]]); - - // Select the first user balance polynomial for the example - let f_poly = advice_polys.advice_polys.get(1).unwrap(); - - let kzg_commitment = commit_kzg(¶ms, &f_poly); - - // Generate a random user index - let get_random_user_index = || { - let user_range: std::ops::Range = 0..N_USERS; - OsRng.gen_range(user_range) as usize - }; - - // Open the polynomial at the user index (challenge) using the naive KZG - let random_user_index = get_random_user_index(); - let challenge = omega.pow_vartime(&[random_user_index as u64]); - - let kzg_proof = create_naive_kzg_proof::>( - ¶ms, - pk.get_vk().get_domain(), - f_poly, - challenge, - big_uint_to_fp(&entries[random_user_index].balances()[0]), - ); - assert!( - verify_kzg_proof( - ¶ms, - kzg_commitment, - kzg_proof, - &challenge, - &big_uint_to_fp(&entries[random_user_index].balances()[0]), - ), - "KZG proof verification failed for user {}", - random_user_index - ); - assert!( - !verify_kzg_proof( - ¶ms, - kzg_commitment, - kzg_proof, - &challenge, - &big_uint_to_fp(&BigUint::from(123u32)), - ), - "Invalid proof verification should fail" - ); - - // Open the polynomial at the user index (challenge) using the amortized KZG - - // Compute the h vector - let timer = start_timer!(|| "Computing h"); - let h = &compute_h_parallel(&[f_poly.clone()], ¶ms, 0..1)[0]; - end_timer!(timer); - - // Demonstrate a single-challenge opening using the calculated h (FK23, eq. 13) - let timer = start_timer!(|| "Computing single amortized proof"); - let single_amortized_proof = &open_single_user_point_amortized(&[h], ¶ms, challenge)[0]; - end_timer!(timer); - - assert!( - *single_amortized_proof == kzg_proof, - "Single challenge amortized KZG proof is not the same as the naive KZG proof" - ); - - // Compute all openings to the polynomial at once using the amortized KZG approach ("CT" in FK23) - let timer = start_timer!(|| "Computing all amortized proofs"); - let amortized_openings = &open_all_user_points_amortized(&[h], omega)[0]; - end_timer!(timer); - - // Check that the amortized opening proof for the user is the same as the naive KZG opening proof - assert!( - amortized_openings[random_user_index] == kzg_proof, - "Amortized KZG proof for user {} is not the same as the naive KZG proof", - random_user_index - ); - - // Verify the amortized KZG opening proof for the user using the same verifier as for the naive KZG proof - assert!( - verify_kzg_proof( - ¶ms, - kzg_commitment, - amortized_openings[random_user_index], - &challenge, - &big_uint_to_fp(&entries[random_user_index].balances()[0]), - ), - "KZG proof verification failed for user {}", - random_user_index - ); - } - - #[test] - fn test_valid_univariate_grand_sum_prover() { - let path = "../csv/entry_16.csv"; - - let mut entries: Vec> = vec![Entry::init_empty(); N_USERS]; - let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES]; - parse_csv_to_entries::<&str, N_CURRENCIES>(path, &mut entries, &mut cryptos).unwrap(); - - let circuit = UnivariateGrandSum::< - N_USERS, - N_CURRENCIES, - UnivariateGrandSumConfig, - >::init(entries.to_vec()); - - let valid_prover = MockProver::run(K, &circuit, vec![vec![Fp::zero()]]).unwrap(); - - assert_eq!(valid_prover.verify_par(), Ok(())) - } - - #[test] - fn test_invalid_instance_value_univariate_grand_sum_prover() { - let path = "../csv/entry_16.csv"; - - let mut entries: Vec> = vec![Entry::init_empty(); N_USERS]; - let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES]; - parse_csv_to_entries::<&str, N_CURRENCIES>(path, &mut entries, &mut cryptos).unwrap(); - - let circuit = UnivariateGrandSum::< - N_USERS, - N_CURRENCIES, - UnivariateGrandSumConfig, - >::init(entries.to_vec()); - - let valid_prover = MockProver::run(K, &circuit, vec![vec![Fp::one()]]).unwrap(); - - let invalid_result = valid_prover.verify_par().unwrap_err()[0].to_string(); - assert!(invalid_result.contains("Equality constraint not satisfied")); - } - - #[test] - fn test_valid_univariate_grand_sum_full_prover() { - let path = "../csv/entry_16.csv"; - - let (entries, circuit, pk, vk, params) = - set_up::>( - path, - ); - - // Calculate total for all entry columns - let mut csv_total: Vec = vec![BigUint::from(0u32); N_CURRENCIES]; - - for entry in &entries { - for (i, balance) in entry.balances().iter().enumerate() { - csv_total[i] += balance; - } - } - - // 1. Proving phase - // The Custodian generates the ZK-SNARK Halo2 proof that commits to the user entry values in advice polynomials - // and also range-checks the user balance values - let (zk_snark_proof, advice_polys, omega) = - full_prover(¶ms, &pk, circuit.clone(), &[vec![Fp::zero()]]); - - // Both the Custodian and the Verifier know what column range are the balance columns - // (The first column is the user IDs) - let balance_column_range = 1..N_CURRENCIES + 1; - - // The Custodian communicates the polynomial length to the Verifier - let poly_length = 1 << u64::from(K); - - // The Custodian makes a batch opening proof of all user balance polynomials at x = 0 for the Verifier - let grand_sums_batch_proof = open_grand_sums( - &advice_polys.advice_polys, - &advice_polys.advice_blinds, - ¶ms, - balance_column_range, - csv_total - .iter() - // The inversion represents the division by the polynomial length (grand total is equal to the constant coefficient times the number of points) - .map(|x| big_uint_to_fp(&(x)) * Fp::from(poly_length).invert().unwrap()) - .collect::>() - .as_slice(), - ); - - // The Custodian creates a KZG batch proof of the 4th user ID & balances inclusion - let user_index = 3_u16; - - let column_range = 0..N_CURRENCIES + 1; - let openings_batch_proof = open_user_points( - &advice_polys.advice_polys, - &advice_polys.advice_blinds, - ¶ms, - column_range, - omega, - user_index, - &entries - .get(user_index as usize) - .map(|entry| { - std::iter::once(big_uint_to_fp(&(entry.username_as_big_uint()))) - .chain(entry.balances().iter().map(|x| big_uint_to_fp(x))) - .collect::>() - }) - .unwrap(), - ); - - // 2. Verification phase - // The Verifier verifies the ZK proof - assert!(full_verifier( - ¶ms, - &vk, - &zk_snark_proof, - &[vec![Fp::zero()]] - )); - - // The Verifier is able to independently extract the omega from the verification key - let omega = pk.get_vk().get_domain().get_omega(); - - // The Custodian communicates the polynomial length to the Verifier - let poly_length = 1 << u64::from(K); - - // Both the Custodian and the Verifier know what column range are the balance columns - let balance_column_range = 1..N_CURRENCIES + 1; - - // The Custodian communicates the KZG batch opening transcript to the Verifier - // The Verifier verifies the KZG batch opening and calculates the grand sums - let (verified, grand_sum) = verify_grand_sum_openings::( - ¶ms, - &zk_snark_proof, - &grand_sums_batch_proof, - poly_length, - balance_column_range, - ); - - assert!(verified); - for i in 0..N_CURRENCIES { - assert_eq!(csv_total[i], grand_sum[i]); - } - - let column_range = 0..N_CURRENCIES + 1; - // The Verifier verifies the inclusion of the 4th user entry - let (inclusion_verified, id_and_balance_values) = verify_user_inclusion( - ¶ms, - &zk_snark_proof, - &openings_batch_proof, - column_range, - omega, - user_index, - ); - - assert!(inclusion_verified); - let fourth_user_csv_entry = entries.get(user_index as usize).unwrap(); - for i in 0..N_CURRENCIES + 1 { - if i == 0 { - assert_eq!( - *fourth_user_csv_entry.username_as_big_uint(), - id_and_balance_values[i] - ); - } else { - assert_eq!( - *fourth_user_csv_entry.balances().get(i - 1).unwrap(), - id_and_balance_values[i] - ); - } - } - } - - // The prover communicates an invalid omega to the verifier, therefore the opening proof of user inclusion should fail - #[test] - fn test_invalid_omega_univariate_grand_sum_proof() { - let path = "../csv/entry_16.csv"; - - let (entries, circuit, pk, vk, params) = - set_up::>( - path, - ); - - // 1. Proving phase - // The Custodian generates the ZK proof - let (zk_snark_proof, advice_polys, omega) = - full_prover(¶ms, &pk, circuit.clone(), &[vec![Fp::zero()]]); - - // The Custodian creates a KZG batch proof of the 4th user ID & balances inclusion - let user_index = 3_u16; - - let column_range = 0..N_CURRENCIES + 1; - let openings_batch_proof = open_user_points( - &advice_polys.advice_polys, - &advice_polys.advice_blinds, - ¶ms, - column_range, - omega, - user_index, - &entries - .get(user_index as usize) - .map(|entry| { - std::iter::once(big_uint_to_fp(&(entry.username_as_big_uint()))) - .chain(entry.balances().iter().map(|x| big_uint_to_fp(x))) - .collect::>() - }) - .unwrap(), - ); - - // 2. Verification phase - // The Verifier verifies the ZK proof - assert!(full_verifier( - ¶ms, - &vk, - &zk_snark_proof, - &[vec![Fp::zero()]] - )); - - // The Verifier is able to independently extract the omega from the verification key - let omega = pk.get_vk().get_domain().get_omega(); - - // Both the Custodian and the Verifier know what column range are the balance columns - let balance_column_range = 1..N_CURRENCIES + 1; - - // Test failure case with the wrong group generator - // Slightly modify the generator - let bad_omega = omega.sub(&Fp::one()); - let (balances_verified, _) = verify_user_inclusion( - ¶ms, - &zk_snark_proof, - &openings_batch_proof, - balance_column_range, - bad_omega, - user_index, - ); - //The verification should fail - assert!(!balances_verified); - } + assert_eq!( + wrong_result, + Err(InvalidSumcheck( + "Consistency failure at round 1".to_string() + )) + ); +} - // The prover communicates an invalid polynomial length to the verifier (smaller than the actual length). This will result in a different grand sum - #[test] - fn test_invalid_poly_length_univariate_grand_sum_full_prover() { - let path = "../csv/entry_16.csv"; +pub fn seeded_std_rng() -> impl RngCore + CryptoRng { + StdRng::seed_from_u64(OsRng.next_u64()) +} - let (entries, circuit, pk, vk, params) = - set_up::>( - path, +#[test] +fn test_summa_hyperplonk() { + type Pb = HyperPlonk>; + let entries = generate_dummy_entries::().unwrap(); + let circuit = SummaHyperplonk::::init(entries.to_vec()); + let num_vars = K; + run_plonkish_backend::, _>( + num_vars.try_into().unwrap(), + |num_vars| { + let circuit = Halo2Circuit::>::new::( + num_vars, + circuit.clone(), ); + (circuit.circuit_info().unwrap(), circuit) + }, + ); +} - // Calculate total for all entry columns - let mut csv_total: Vec = vec![BigUint::from(0u32); N_CURRENCIES]; - - for entry in &entries { - for (i, balance) in entry.balances().iter().enumerate() { - csv_total[i] += balance; - } - } - - // 1. Proving phase - // The Custodian generates the ZK-SNARK Halo2 proof that commits to the user entry values in advice polynomials - // and also range-checks the user balance values - let (zk_snark_proof, advice_polys, _) = - full_prover(¶ms, &pk, circuit.clone(), &[vec![Fp::zero()]]); - - // Both the Custodian and the Verifier know what column range are the balance columns - // (The first column is the user IDs) - let balance_column_range = 1..N_CURRENCIES + 1; - - // The Custodian communicates the polynomial length to the Verifier - let poly_length = 1 << u64::from(K); - - // The Custodian makes a batch opening proof of all user balance polynomials at x = 0 for the Verifier - let grand_sums_batch_proof = open_grand_sums( - &advice_polys.advice_polys, - &advice_polys.advice_blinds, - ¶ms, - balance_column_range, - csv_total - .iter() - .map(|x| big_uint_to_fp(&(x)) * Fp::from(poly_length).invert().unwrap()) - .collect::>() - .as_slice(), - ); - - // 2. Verification phase - // The Verifier verifies the ZK proof - assert!(full_verifier( - ¶ms, - &vk, - &zk_snark_proof, - &[vec![Fp::zero()]] - )); - - // The Custodian communicates the (invalid) polynomial length to the Verifier - let invalid_poly_length = 2 ^ u64::from(K) - 1; - - // Both the Custodian and the Verifier know what column range are the balance columns - let balance_column_range = 1..N_CURRENCIES + 1; - - // The Custodian communicates the KZG batch opening transcript to the Verifier - // The Verifier verifies the KZG batch opening and calculates the grand sums - let (verified, grand_sum) = verify_grand_sum_openings::( - ¶ms, - &zk_snark_proof, - &grand_sums_batch_proof, - invalid_poly_length, - balance_column_range, - ); - - // The opened grand sum is not equal to the actual sum of balances extracted from the csv file - assert!(verified); - for i in 0..N_CURRENCIES { - assert_ne!(csv_total[i], grand_sum[i]); - } - } - - // Building a proof using as input a csv file with an entry that is not in range [0, 2^64 - 1] should fail the range check constraint on the leaf balance - #[test] - fn test_balance_not_in_range() { - let path = "../csv/entry_16_overflow.csv"; - - let mut entries: Vec> = vec![Entry::init_empty(); N_USERS]; - let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES]; - parse_csv_to_entries::<&str, N_CURRENCIES>(path, &mut entries, &mut cryptos).unwrap(); - - let circuit = UnivariateGrandSum::< - N_USERS, - N_CURRENCIES, - UnivariateGrandSumConfig, - >::init(entries.to_vec()); - - let invalid_prover = MockProver::run(K, &circuit, vec![vec![Fp::zero()]]).unwrap(); - - assert_eq!( - invalid_prover.verify(), - Err(vec![ - VerifyFailure::Permutation { - column: (Any::advice(), 6).into(), - location: FailureLocation::InRegion { - region: (2, "Perform range check on balance 0 of user 0").into(), - offset: 0 - } - }, - VerifyFailure::Permutation { - column: (Any::advice(), 6).into(), - location: FailureLocation::InRegion { - region: (6, "Perform range check on balance 0 of user 2").into(), - offset: 0 - } - }, - VerifyFailure::Permutation { - column: (Any::advice(), 10).into(), - location: FailureLocation::InRegion { - region: (3, "Perform range check on balance 1 of user 0").into(), - offset: 0 - } - }, - VerifyFailure::Permutation { - column: (Any::advice(), 10).into(), - location: FailureLocation::InRegion { - region: (5, "Perform range check on balance 1 of user 1").into(), - offset: 0 - } - }, - ]) - ); - } - - #[cfg(feature = "dev-graph")] - #[test] - fn print_univariate_grand_sum_circuit() { - use plotters::prelude::*; - - let path = "../csv/entry_16.csv"; - - let mut entries: Vec> = vec![Entry::init_empty(); N_USERS]; - let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES]; - let _ = - parse_csv_to_entries::<&str, N_CURRENCIES>(path, &mut entries, &mut cryptos).unwrap(); - - let circuit = UnivariateGrandSum::< - N_USERS, - N_CURRENCIES, - UnivariateGrandSumConfig, - >::init(entries); - - let root = BitMapBackend::new("prints/univariate-grand-sum-layout.png", (2048, 32768)) - .into_drawing_area(); - root.fill(&WHITE).unwrap(); - let root = root - .titled("Univariate Grand Sum Layout", ("sans-serif", 60)) - .unwrap(); - - halo2_proofs::dev::CircuitLayout::default() - .render(K, &circuit, &root) - .unwrap(); - } - - fn set_up< - const K: u32, - const N_USERS: usize, - const N_CURRENCIES: usize, - CONFIG: CircuitConfig, - >( - path: &str, - ) -> ( - Vec>, - UnivariateGrandSum, - ProvingKey, - VerifyingKey, - ParamsKZG, - ) - where - [(); N_CURRENCIES + 1]:, - { - // Initialize an empty circuit - let circuit = UnivariateGrandSum::::init_empty(); - - // Generate a universal trusted setup for testing purposes. - // - // The verification key (vk) and the proving key (pk) are then generated. - // An empty circuit is used here to emphasize that the circuit inputs are not relevant when generating the keys. - // Important: The dimensions of the circuit used to generate the keys must match those of the circuit used to generate the proof. - // In this case, the dimensions are represented by the number fo users. - let (params, pk, vk) = generate_setup_artifacts(K, None, &circuit).unwrap(); +#[cfg(feature = "dev-graph")] +#[test] +fn print_univariate_grand_sum_circuit() { + use plotters::prelude::*; - // Only now we can instantiate the circuit with the actual inputs - let mut entries: Vec> = vec![Entry::init_empty(); N_USERS]; - let mut cryptos = vec![Cryptocurrency::init_empty(); N_CURRENCIES]; + let entries = generate_dummy_entries::().unwrap(); - parse_csv_to_entries::<&str, N_CURRENCIES>(path, &mut entries, &mut cryptos).unwrap(); + let circuit = SummaHyperplonk::::init(entries.to_vec()); - let circuit = UnivariateGrandSum::::init(entries.to_vec()); + let root = + BitMapBackend::new("prints/summa-hyperplonk-layout.png", (2048, 32768)).into_drawing_area(); + root.fill(&WHITE).unwrap(); + let root = root + .titled("Summa Hyperplonk Layout", ("sans-serif", 60)) + .unwrap(); - (entries, circuit, pk, vk, params) - } + halo2_proofs::dev::CircuitLayout::default() + .render::, _, true>(K, &circuit, &root) + .unwrap(); } diff --git a/prover/src/circuits/univariate_grand_sum.rs b/prover/src/circuits/univariate_grand_sum.rs deleted file mode 100644 index 75f60b41..00000000 --- a/prover/src/circuits/univariate_grand_sum.rs +++ /dev/null @@ -1,325 +0,0 @@ -use std::marker::PhantomData; - -use crate::chips::range::range_check::{RangeCheckU64Chip, RangeCheckU64Config}; -use crate::entry::Entry; -use crate::utils::big_uint_to_fp; -use halo2_proofs::circuit::{AssignedCell, Layouter, SimpleFloorPlanner, Value}; -use halo2_proofs::halo2curves::bn256::Fr as Fp; -use halo2_proofs::plonk::{Advice, Circuit, Column, ConstraintSystem, Error, Fixed, Instance}; - -#[derive(Clone)] -pub struct UnivariateGrandSum< - const N_USERS: usize, - const N_CURRENCIES: usize, - CONFIG: CircuitConfig, -> { - pub entries: Vec>, - _marker: PhantomData, -} - -impl< - const N_USERS: usize, - const N_CURRENCIES: usize, - CONFIG: CircuitConfig, - > UnivariateGrandSum -{ - pub fn init_empty() -> Self - where - [(); N_CURRENCIES + 1]:, - { - Self { - entries: vec![Entry::init_empty(); N_USERS], - _marker: PhantomData, - } - } - - /// Initializes the circuit with the user entries that are part of the solvency proof - pub fn init(user_entries: Vec>) -> Self { - Self { - entries: user_entries, - _marker: PhantomData, - } - } -} - -/// Configuration for the univariate grand sum circuit -/// # Type Parameters -/// -/// * `N_CURRENCIES`: The number of currencies for which the solvency is verified. -/// * `N_USERS`: The number of users for which the solvency is verified. -/// -/// # Fields -/// -/// * `username`: Advice column used to store the usernames of the users -/// * `balances`: Advice columns used to store the balances of the users -/// * `range_check_configs`: Configurations for the range check chip -/// * `range_u16`: Fixed column used to store the lookup table [0, 2^16 - 1] for the range check chip -#[derive(Debug, Clone)] -pub struct UnivariateGrandSumConfig -where - [(); N_CURRENCIES + 1]:, -{ - username: Column, - balances: [Column; N_CURRENCIES], - range_check_configs: [RangeCheckU64Config; N_CURRENCIES], - range_u16: Column, - instance: Column, -} - -impl CircuitConfig - for UnivariateGrandSumConfig -where - [(); N_CURRENCIES + 1]:, -{ - fn configure(meta: &mut ConstraintSystem) -> Self { - let username = meta.advice_column(); - - let balances = [(); N_CURRENCIES].map(|_| meta.unblinded_advice_column()); - - let range_u16 = meta.fixed_column(); - - meta.enable_constant(range_u16); - - meta.annotate_lookup_any_column(range_u16, || "LOOKUP_MAXBITS_RANGE"); - - // Create an empty array of range check configs - let mut range_check_configs = Vec::with_capacity(N_CURRENCIES); - - let instance = meta.instance_column(); - meta.enable_equality(instance); - - for item in balances.iter().take(N_CURRENCIES) { - let z = *item; - // Create 4 advice columns for each range check chip - let zs = [(); 4].map(|_| meta.advice_column()); - - for column in &zs { - meta.enable_equality(*column); - } - - let range_check_config = RangeCheckU64Chip::configure(meta, z, zs, range_u16); - - range_check_configs.push(range_check_config); - } - - Self { - username, - balances, - range_check_configs: range_check_configs.try_into().unwrap(), - range_u16, - instance, - } - } - - fn synthesize( - &self, - mut layouter: impl Layouter, - assigned_balances: Vec>>, - ) -> Result<(), Error> - where - [(); N_CURRENCIES + 1]:, - [(); N_CURRENCIES + 1]:, - { - // Initiate the range check chips - let range_check_chips = self - .range_check_configs - .iter() - .map(|config| RangeCheckU64Chip::construct(*config)) - .collect::>(); - - // Load lookup table for range check u64 chip - let range = 1 << 16; - - layouter.assign_region( - || format!("load range check table of 16 bits"), - |mut region| { - for i in 0..range { - region.assign_fixed( - || "assign cell in fixed column", - self.range_u16, - i, - || Value::known(Fp::from(i as u64)), - )?; - } - Ok(()) - }, - )?; - - // Perform range check on the assigned balances - for i in 0..N_USERS { - for j in 0..N_CURRENCIES { - let mut zs = Vec::with_capacity(4); - - layouter.assign_region( - || format!("Perform range check on balance {} of user {}", j, i), - |mut region| { - range_check_chips[j].assign( - &mut region, - &mut zs, - &assigned_balances[i][j], - )?; - Ok(()) - }, - )?; - - layouter.constrain_instance(zs[3].cell(), self.instance, 0)?; - } - } - - Ok(()) - } - - fn get_username(&self) -> Column { - self.username - } - - fn get_balances(&self) -> [Column; N_CURRENCIES] { - self.balances - } -} - -pub trait CircuitConfig: Clone { - fn configure(meta: &mut ConstraintSystem) -> Self; - - fn get_username(&self) -> Column; - - fn get_balances(&self) -> [Column; N_CURRENCIES]; - - fn synthesize( - &self, - layouter: impl Layouter, - assigned_balances: Vec>>, - ) -> Result<(), Error>; - - /// Assigns the entries to the circuit - /// At row i, the username is set to the username of the i-th entry, the balance is set to the balance of the i-th entry - /// Returns a bidimensional vector of the assigned balances to the circuit. - fn assign_entries( - &self, - mut layouter: impl Layouter, - entries: &[Entry], - ) -> Result>>, Error> - where - [(); N_CURRENCIES + 1]:, - { - layouter.assign_region( - || "assign entries to the table", - |mut region| { - // create a bidimensional vector to store the assigned balances. The first dimension is N_USERS, the second dimension is N_CURRENCIES - let mut assigned_balances = vec![]; - - for i in 0..N_USERS { - region.assign_advice( - || "username", - self.get_username(), - i, - || Value::known(big_uint_to_fp(entries[i].username_as_big_uint())), - )?; - - let mut assigned_balances_row = vec![]; - - for (j, balance) in entries[i].balances().iter().enumerate() { - let assigned_balance = region.assign_advice( - || format!("balance {}", j), - self.get_balances()[j], - i, - || Value::known(big_uint_to_fp(balance)), - )?; - - assigned_balances_row.push(assigned_balance); - } - - assigned_balances.push(assigned_balances_row); - } - - Ok(assigned_balances) - }, - ) - } -} - -impl< - const N_USERS: usize, - const N_CURRENCIES: usize, - CONFIG: CircuitConfig, - > Circuit for UnivariateGrandSum -where - [(); N_CURRENCIES + 1]:, -{ - type Config = CONFIG; - type FloorPlanner = SimpleFloorPlanner; - - fn without_witnesses(&self) -> Self { - Self::init_empty() - } - - fn configure(meta: &mut ConstraintSystem) -> Self::Config - where - [(); N_CURRENCIES + 1]:, - { - CONFIG::configure(meta) - } - - fn synthesize( - &self, - config: Self::Config, - mut layouter: impl Layouter, - ) -> Result<(), Error> { - // Assign entries - let assigned_balances = - config.assign_entries(layouter.namespace(|| "assign entries"), &self.entries)?; - - config.synthesize(layouter, assigned_balances) - } -} - -/// Configuration that does not perform range checks. Warning: not for use in production! -/// The circuit without range checks can use a lower K value than the full circuit (convenient for prototyping and testing). -/// -/// # Type Parameters -/// -/// * `N_CURRENCIES`: The number of currencies for which the solvency is verified. -/// * `N_USERS`: The number of users for which the solvency is verified. -/// -/// # Fields -/// -/// * `username`: Advice column used to store the usernames of the users -/// * `balances`: Advice columns used to store the balances of the users -#[derive(Clone)] -pub struct NoRangeCheckConfig { - username: Column, - balances: [Column; N_CURRENCIES], -} - -impl CircuitConfig - for NoRangeCheckConfig -where - [(); N_CURRENCIES + 1]:, -{ - fn configure(meta: &mut ConstraintSystem) -> NoRangeCheckConfig { - let username = meta.advice_column(); - - let balances = [(); N_CURRENCIES].map(|_| meta.unblinded_advice_column()); - - let instance = meta.instance_column(); - meta.enable_equality(instance); - - Self { username, balances } - } - - fn synthesize( - &self, - _: impl Layouter, - _: Vec>>, - ) -> Result<(), Error> { - Ok(()) - } - - fn get_username(&self) -> Column { - self.username - } - - fn get_balances(&self) -> [Column; N_CURRENCIES] { - self.balances - } -} diff --git a/prover/src/circuits/utils.rs b/prover/src/circuits/utils.rs deleted file mode 100644 index eefb06ef..00000000 --- a/prover/src/circuits/utils.rs +++ /dev/null @@ -1,561 +0,0 @@ -use std::{fs::File, ops::Range}; - -use ark_std::{end_timer, start_timer}; -use ethers::types::U256; -use halo2_proofs::{ - arithmetic::{best_fft, best_multiexp, parallelize, Field}, - halo2curves::{ - bn256::{Bn256, Fr as Fp, G1Affine, G1}, - ff::{PrimeField, WithSmallOrderMulGroup}, - group::Curve, - }, - plonk::{ - create_proof, keygen_pk, keygen_vk, verify_proof, AdviceSingle, Circuit, Error, ProvingKey, - VerifyingKey, - }, - poly::{ - commitment::{Blind, CommitmentScheme, Params, Prover, Verifier}, - kzg::{ - commitment::{KZGCommitmentScheme, ParamsKZG}, - multiopen::{ProverGWC, ProverSHPLONK, VerifierSHPLONK}, - strategy::SingleStrategy, - }, - Coeff, Polynomial, ProverQuery, VerificationStrategy, VerifierQuery, - }, - transcript::{EncodedChallenge, TranscriptRead, TranscriptWriterBuffer}, -}; -use halo2_solidity_verifier::Keccak256Transcript; -use num_bigint::BigUint; -use rand::rngs::OsRng; -use rayon::prelude::*; - -use crate::utils::{amortized_kzg::compute_h, fp_to_big_uint}; - -/// Generate setup artifacts for a circuit of size `k`, where 2^k represents the number of rows in the circuit. -/// -/// If the trusted setup parameters are not found, the function performs an unsafe trusted setup to generate the necessary parameters -/// If the provided `k` value is larger than the `k` value of the loaded parameters, an error is returned, as the provided `k` is too large. -/// Otherwise, if the `k` value is smaller than the `k` value of the loaded parameters, the parameters are downsized to fit the requested `k`. -pub fn generate_setup_artifacts>( - k: u32, - params_path: Option<&str>, - circuit: &C, -) -> Result< - ( - ParamsKZG, - ProvingKey, - VerifyingKey, - ), - &'static str, -> { - let mut params: ParamsKZG; - - match params_path { - Some(path) => { - let timer = start_timer!(|| "Creating params"); - let mut params_fs = File::open(path).expect("couldn't load params"); - params = ParamsKZG::::read(&mut params_fs).expect("Failed to read params"); - end_timer!(timer); - - if params.k() < k { - return Err("k is too large for the given params"); - } - - if params.k() > k { - let timer = start_timer!(|| "Downsizing params"); - params.downsize(k); - end_timer!(timer); - } - } - None => { - let timer = start_timer!(|| "None Creating params"); - params = ParamsKZG::::setup(k, OsRng); - end_timer!(timer); - } - } - - let vk = keygen_vk(¶ms, circuit).expect("vk generation should not fail"); - let pk = keygen_pk(¶ms, vk.clone(), circuit).expect("pk generation should not fail"); - - Ok((params, pk, vk)) -} - -/// Generates a proof given the public setup, the proving key, the initialized circuit and its public inputs. -pub fn full_prover>( - params: &ParamsKZG, - pk: &ProvingKey, - circuit: C, - public_inputs: &[Vec], -) -> ( - Vec, - AdviceSingle, - Fp, -) { - #[cfg(feature = "profiling")] - let pf_time = start_timer!(|| "Creating proof"); - - let instance: Vec<&[Fp]> = public_inputs.iter().map(|input| &input[..]).collect(); - let instances = &[&instance[..]]; - - let mut transcript: Keccak256Transcript> = Keccak256Transcript::new(vec![]); - let result = create_proof::< - KZGCommitmentScheme, - ProverSHPLONK<'_, Bn256>, - _, - _, - Keccak256Transcript>, - _, - >(params, pk, &[circuit], instances, OsRng, &mut transcript); - - let result_unwrapped = result.unwrap(); - result_unwrapped.0.expect("prover should not fail"); - let advice_polys = result_unwrapped.1.clone(); - let proof = transcript.finalize(); - - #[cfg(feature = "profiling")] - end_timer!(pf_time); - let advice_polys = advice_polys[0].clone(); - - let omega = pk.get_vk().get_domain().get_omega(); - - (proof, advice_polys, omega) -} - -/// Creates the univariate polynomial grand sum openings. -/// The polynomials are evaluated at X = 0 to obtain their constant term. -/// -/// # Arguments -/// -/// * `advice_polys` - the advice polynomials -/// * `advice_blinds` - the advice polynomials blinds -/// * `params` - the KZG parameters -/// * `balance_column_range` - the range of the balance columns used to calculate the grand sums -/// * `constant_terms` - the evaluations of the polynomials at X = 0 -/// -/// # Returns -/// -/// * `Vec` - the KZG batch proof containing the quotient polynomial commitments -/// and the evaluations of the polynomials at X = 0 -pub fn open_grand_sums( - advice_polys: &[Polynomial], - advice_blinds: &[Blind], - params: &ParamsKZG, - balance_column_range: Range, - constant_terms: &[Fp], -) -> Vec { - let challenge = Fp::zero(); - create_opening_proof_at_challenge::< - _, - ProverSHPLONK<'_, Bn256>, - _, - Keccak256Transcript>, - >( - params, - &advice_polys[balance_column_range], - advice_blinds, - challenge, - constant_terms, - ) -} - -// This function is for comparison with open_grand_sums and is using GWC instead of ProverSHPLONK -pub fn open_grand_sums_gwc( - advice_polys: &[Polynomial], - advice_blinds: &[Blind], - params: &ParamsKZG, - balance_column_range: Range, - constant_terms: &[Fp], -) -> Vec { - let challenge = Fp::zero(); - create_opening_proof_at_challenge::< - _, - ProverGWC<'_, Bn256>, - _, - Keccak256Transcript>, - >( - params, - &advice_polys[balance_column_range], - advice_blinds, - challenge, - constant_terms, - ) -} - -/// Creates a KZG batch proof for the `advice_polys` polynomial openings -/// at a point corresponding to the `user_index` -/// -/// # Arguments -/// -/// * `advice_polys` - the advice polynomials -/// * `advice_blinds` - the advice polynomials blinds -/// * `params` - the KZG parameters -/// * `column_range` - the advice column range to be used for the proof -/// * `omega` - $\omega$, the generator of the $2^k$ order multiplicative subgroup used to interpolate the polynomials. -/// * `user_index` - the index of the user whose entry is being proven -/// * `user_balances` - the evaluations of the polynomials at the point corresponding to the `user_index` -/// -/// # Returns -/// -/// * `Vec` - the KZG batch proof containing the quotient polynomial commitments -/// and the evaluations of the polynomials at the point corresponding to the `user_index` -pub fn open_user_points( - advice_polys: &[Polynomial], - advice_blinds: &[Blind], - params: &ParamsKZG, - column_range: Range, - omega: Fp, - user_index: u16, - user_balances: &[Fp], -) -> Vec { - let omega_raised = omega.pow_vartime([u64::from(user_index)]); - create_opening_proof_at_challenge::< - _, - ProverSHPLONK<'_, Bn256>, - _, - Keccak256Transcript>, - >( - params, - &advice_polys[column_range], - advice_blinds, - omega_raised, - user_balances, - ) -} - -/// Calculate h(x) for the amortized KZG algorithm as per FK23 for all advice polynomials in the range in parallel -/// -/// # Arguments -/// -/// * `advice_polys` - the advice polynomials -/// * `params` - the KZG parameters -/// * `column_range` - the range of the advice columns of interest -/// -/// # Returns -/// -/// * `Vec>` - h(x) vectors corresponding to the polynomials -pub fn compute_h_parallel( - advice_polys: &[Polynomial], - params: &ParamsKZG, - column_range: Range, -) -> Vec> { - advice_polys[column_range] - // Parallelize the independent amortized openings of the user ID and balance polynomials - .par_iter() - .map(|poly| compute_h(params, poly)) - .collect() -} - -/// Calculate all opening proofs at once for the polynomials using the amortized KZG approach -/// -/// # Arguments -/// -/// * `h_vectors` - the h(X) vectors calculated for the polynomials using the amortized KZG approach -/// * `omega` - $\omega$, the generator of the multiplicative subgroup used to interpolate the polynomials. -/// -/// # Returns -/// -/// * `Vec>` - all KZG opening proofs for the polynomials in the range -pub fn open_all_user_points_amortized(h_vectors: &[&[G1]], omega: Fp) -> Vec> { - h_vectors - // Parallelize the independent amortized openings of the user ID and balance polynomials - .par_iter() - .map(|h_vector| { - let mut h: Vec = (*h_vector).to_vec(); - best_fft(&mut h, omega, h_vector.len().trailing_zeros()); - h - }) - .collect() -} - -/// Calculate a single-user opening proofs using the amortized KZG approach -/// -/// # Arguments -/// -/// * `h_vectors` - the h(X) vectors calculated for the polynomials using the amortized KZG approach -/// * `params` - the KZG parameters -/// * `challenge` - the challenge at which the openings are evaluated -/// -/// # Returns -/// -/// * `Vec` - the KZG opening proofs for the polynomials at `challenge` -pub fn open_single_user_point_amortized( - h_vectors: &[&[G1]], - params: &ParamsKZG, - challenge: Fp, -) -> Vec { - let mut challenge_powers = vec![Fp::one(); params.n() as usize]; - { - parallelize(&mut challenge_powers, |o, start| { - let mut cur = challenge.pow_vartime([start as u64]); - for v in o.iter_mut() { - *v = cur; - cur *= &challenge; - } - }) - } - // Convert the h vectors to affine form and calculate the opening proofs - h_vectors - .par_iter() - .map(|h_vector| { - let h_affine = (*h_vector) - .par_iter() - .map(G1::to_affine) - .collect::>(); - best_multiexp(&challenge_powers, &h_affine) - }) - .collect::>() -} - -/// Verifies the univariate polynomial grand sum openings -/// and calculates the grand sums -/// -/// * `N_CURRENCIES` - the number of cryptocurrency balances -/// -/// # Arguments -/// -/// * `params` - the KZG parameters -/// * `zk_snark_proof` - the ZK-SNARK proof of the circuit whose advice columns contain the user balance polynomials -/// * `grand_sum_opening_batch_proof` - the KZG batch proof of the grand sum polynomials -/// * `polynomial_length` - the length of the polynomials -/// * `balance_column_range` - the range of the advice columns that represent user balances -/// -/// # Returns -/// -/// * `bool` - whether the grand sum openings are verified correctly -/// * `Vec` - the grand sums -pub fn verify_grand_sum_openings( - params: &ParamsKZG, - zk_snark_proof: &[u8], - grand_sum_opening_batch_proof: &[u8], - polynomial_length: u64, - balance_column_range: Range, -) -> (bool, Vec) { - let mut transcript = Keccak256Transcript::new(zk_snark_proof); - - //Read the commitment points for all the advice polynomials from the proof transcript and put them into a vector - let mut advice_commitments = Vec::new(); - for i in 0..N_CURRENCIES + balance_column_range.start { - let point = transcript.read_point().unwrap(); - // Skip the advice commitments before the desired range - if i >= balance_column_range.start { - advice_commitments.push(point); - } - } - - let opening_result = - verify_opening::, VerifierSHPLONK, SingleStrategy<_>>( - params, - grand_sum_opening_batch_proof, - Fp::zero(), - &advice_commitments, - ); - - match opening_result { - Ok((verified, evaluations)) => ( - verified, - evaluations - .iter() - .map(|eval| fp_to_big_uint(*eval * Fp::from(polynomial_length))) - .collect(), - ), - Err(_) => (false, vec![]), - } -} - -/// Verifies the KZG batch proof of the polynomial openings being the evaluations -/// of the advice polynomials at the point corresponding to the user index -/// -/// # Arguments -/// * `params` - the KZG parameters -/// * `zk_snark_proof` - the ZK-SNARK proof of the circuit whose advice columns contain the user entry polynomials -/// * `balance_opening_batch_proof` - the KZG batch proof of the user entry polynomials -/// * `column_range` - the range of the advice columns that represent user entry -/// * `omega` - $\omega$, the generator of the $2^k$ order multiplicative subgroup used to interpolate the polynomials. -/// * `user_index` - the index of the user whose entry is being proven -/// -/// # Returns -/// * `bool` - whether the user entry openings are verified correctly -/// * `Vec` - the evaluations of the advice polynomials at the point corresponding to the user index -pub fn verify_user_inclusion( - params: &ParamsKZG, - zk_snark_proof: &[u8], - balance_opening_batch_proof: &[u8], - column_range: Range, - omega: Fp, - user_index: u16, -) -> (bool, Vec) { - let mut transcript = Keccak256Transcript::new(zk_snark_proof); - - //Read the commitment points for all the advice polynomials from the proof transcript and put them into a vector - let mut advice_commitments = Vec::new(); - for i in 0..column_range.end { - let point = transcript.read_point().unwrap(); - //Skip advice polynomial commitments before the desired range - if i >= column_range.start { - advice_commitments.push(point); - } - } - - let opening_result = - verify_opening::, VerifierSHPLONK, SingleStrategy<_>>( - params, - balance_opening_batch_proof, - omega.pow_vartime([user_index as u64]), - &advice_commitments, - ); - - // return result error if it exists - match opening_result { - Ok((verified, evaluations)) => ( - verified, - evaluations - .iter() - .map(|eval| fp_to_big_uint(*eval)) - .collect(), - ), - Err(_) => (false, vec![]), - } -} - -/// Creates a KZG batch proof for the polynomial evaluations at a challenge -/// -/// # Arguments -/// -/// * `params` - the KZG parameters -/// * `polynomials` - the polynomials to be opened -/// * `blinds` - the polynomials blinds -/// * `challenge` - the challenge at which the polynomials are evaluated -/// * `polynomial_evaluations` - the evaluations of the polynomials at the challenge -/// -/// # Returns -/// -/// * `Vec` containing the quotient polynomial commitments -/// and the evaluations of the polynomials at the challenge -fn create_opening_proof_at_challenge< - 'params, - Scheme: CommitmentScheme, - P: Prover<'params, Scheme>, - E: EncodedChallenge, - T: TranscriptWriterBuffer, Scheme::Curve, E>, ->( - params: &'params Scheme::ParamsProver, - polynomials: &[Polynomial<::Scalar, Coeff>], - blinds: &[Blind], - challenge: Fp, - polynomial_evaluations: &[Fp], -) -> Vec -where - Scheme::Scalar: WithSmallOrderMulGroup<3>, -{ - let mut transcript = T::init(vec![]); - - // Write evaluations to the transcript - polynomial_evaluations - .iter() - .for_each(|eval| transcript.write_scalar(*eval).unwrap()); - - // Prepare prover queries for the polynomial - let queries = polynomials - .iter() - .enumerate() - .map(|(i, polynomial)| ProverQuery::new(challenge, polynomial, blinds[i])) - .collect::>(); - - // Create proof - let prover = P::new(params); - prover - .create_proof(&mut OsRng, &mut transcript, queries) - .unwrap(); - - // Finalize transcript and return the proof - transcript.finalize() -} - -/// Verifies a KZG batch proof for a polynomial evaluation at a challenge -/// and returns the evaluations of the polynomials at the challenge -/// as well as the verification result -/// -/// # Arguments -/// -/// * `params` - the KZG parameters -/// * `proof` - the KZG batch proof -/// * `challenge` - the challenge at which the polynomials are evaluated -/// * `commitment_points` - the commitment points of the polynomials -/// -/// # Returns -/// -/// * `bool` - whether the proof is verified correctly -/// * `Vec` - the evaluations of the polynomials at the challenge -pub fn verify_opening< - 'a, - 'params, - Scheme: CommitmentScheme, - V: Verifier<'params, Scheme>, - Strategy: VerificationStrategy<'params, Scheme, V>, ->( - params: &'params Scheme::ParamsVerifier, - proof: &'a [u8], - challenge: Fp, - commitment_points: &[G1Affine], -) -> Result<(bool, Vec), Box> -where - Scheme::Scalar: WithSmallOrderMulGroup<3>, -{ - let mut transcript = Keccak256Transcript::new(proof); - - // Read the polynomial evaluations from the transcript - let n_points = commitment_points.len(); - let evaluations = (0..n_points) - .map(|_| transcript.read_scalar().unwrap()) - .collect::>(); - - // Prepare verifier queries for the commitment - let queries = (0..n_points) - .map(|i| VerifierQuery::new_commitment(&commitment_points[i], challenge, evaluations[i])) - .collect::>(); - - // Initialize the verifier - let verifier = V::new(params); - - // Use the provided strategy for verification - let strategy = Strategy::new(params); - let result = strategy.process(|msm_accumulator| { - verifier - .verify_proof(&mut transcript, queries.iter().cloned(), msm_accumulator) - .map_err(|_| Error::Opening) - }); - - // `strategy.process`` return () without any error means the proof is verified - match result { - Err(e) => Err(Box::new(e)), - _ => Ok((true, evaluations)), - } -} - -/// Verifies a proof given the public setup, the verification key, the proof and the public inputs of the circuit. -pub fn full_verifier( - params: &ParamsKZG, - vk: &VerifyingKey, - proof: &[u8], - public_inputs: &[Vec], -) -> bool { - let instance: Vec<&[Fp]> = public_inputs.iter().map(|input| &input[..]).collect(); - let instances = &[&instance[..]]; - - let mut transcript = Keccak256Transcript::new(proof); - verify_proof::<_, VerifierSHPLONK<_>, _, _, _>( - params, - vk, - SingleStrategy::new(params), - instances, - &mut transcript, - ) - .is_ok() -} - -/// Converts a field element to a Solidity calldata -pub fn field_element_to_solidity_calldata(field_element: Fp) -> U256 { - let bytes = field_element.to_repr(); - let u = U256::from_little_endian(bytes.as_slice()); - u -} diff --git a/prover/src/lib.rs b/prover/src/lib.rs index 5da86c4c..2c750442 100644 --- a/prover/src/lib.rs +++ b/prover/src/lib.rs @@ -1,13 +1,6 @@ -//! This crate contains the cryptogarphic primitives for implementing proof of solvency protocol. -//! The tooling being used to generate the zkSNARKs is [Halo2 PSE Fork](https://github.com/privacy-scaling-explorations/halo2). - -#![feature(generic_const_exprs)] - -/// Zk circuit subcomponents aka chips. pub mod chips; -/// Zk circuits with a full prover and verifier. A circuit can be viewed as an assembly of chips. pub mod circuits; pub mod cryptocurrency; pub mod entry; -/// Utilities to build the merkle sum tree data structure. No zk proof in here. + pub mod utils; diff --git a/prover/src/utils/amortized_kzg.rs b/prover/src/utils/amortized_kzg.rs deleted file mode 100644 index fd4afb97..00000000 --- a/prover/src/utils/amortized_kzg.rs +++ /dev/null @@ -1,154 +0,0 @@ -use halo2_proofs::{ - arithmetic::{best_fft, kate_division, Field}, - halo2curves::{ - bn256::{Bn256, Fr as Fp, G1Affine, G2Affine, Gt, G1}, - group::{prime::PrimeCurveAffine, Curve, Group}, - pairing::{Engine, PairingCurveAffine}, - }, - poly::{ - commitment::{Blind, CommitmentScheme, Params, ParamsProver}, - kzg::commitment::ParamsKZG, - Coeff, EvaluationDomain, Polynomial, - }, -}; -use rayon::iter::{ - IndexedParallelIterator, IntoParallelRefIterator, IntoParallelRefMutIterator, ParallelIterator, -}; - -/// Commit to a polynomial using the KZG commitment scheme -/// -/// # Arguments -/// -/// * `params` - The KZG parameters -/// * `poly` - The polynomial to commit to -/// -/// # Returns -/// -/// * The commitment to the polynomial as the G1 point -pub fn commit_kzg(params: &ParamsKZG, poly: &Polynomial) -> G1 { - params.commit(poly, Blind::default()) -} - -/// Computes the polynomial h(X) for the amortized KZG algorithm as per FK23 -/// https://eprint.iacr.org/2023/033 -/// -/// # Arguments -/// -/// * `params` - The KZG parameters -/// * `f_poly` - The polynomial to compute the amortized opening proof for -/// -/// # Returns -/// -/// * The polynomial h(X) as a vector of G1 points -pub fn compute_h(params: &ParamsKZG, f_poly: &Polynomial) -> Vec { - // Double the polynomial length, thus K + 1 - let double_domain = EvaluationDomain::new(1, params.k() + 1); - - let d: usize = f_poly.len(); // Degree of the polynomial - - // Extract s_commitments from ParamsKZG, reverse and extend with neutral elements - let s_commitments_reversed = params - .get_g() - .par_iter() - .rev() - .map(PrimeCurveAffine::to_curve) - .collect::>(); - - let mut y: Vec = vec![G1::identity(); 2 * d]; - y[..d].copy_from_slice(&s_commitments_reversed[..d]); - - // Prepare coefficients vector and zero-pad at the beginning - let mut v = vec![Fp::zero(); 2 * d]; - v[d..(2 * d)].copy_from_slice(f_poly); - - let nu = double_domain.get_omega(); // 2d-th root of unity - - rayon::join( - || best_fft(&mut y, nu, (2 * d).trailing_zeros()), // Perform the step 1 FFT from FK23, §2.2 - || best_fft(&mut v, nu, (2 * d).trailing_zeros()), // Perform the step 2 FFT from FK23, §2.2 - ); - - // Perform the Hadamard product (FK23, §2.2, step 3) - let u: Vec = y - .par_iter() - .zip(v.par_iter()) - .map(|(&y, &v)| y * v) - .collect(); - - let nu_inv = nu.invert().unwrap(); // Inverse of 2d-th root of unity - let mut h = u; - // Perform inverse FFT on h (FK23, §2.2, step 4) - best_fft(&mut h, nu_inv, (2 * d).trailing_zeros()); - - // Scale the result by the size of the vector (part of the iFFT) - let n_inv = Fp::from(2 * d as u64).invert().unwrap(); - h.par_iter_mut().map(|h| *h *= n_inv).collect::>(); - - // Truncate to get the first d coefficients (FK23, §2.2, step 5) - h.truncate(d); - - h -} - -/// Compute the naive KZG opening proof -/// J Thaler, Proofs, Arguments, and Zero-Knowledge, §15.2, p. 233 -/// KZG proof π is a proof of f(y) = z: π[f(y) = z] = C_Ty, where C_Ty is a commitment to a polynomial Ty(X) = (f(X)−z)/(X−y) and y is the challenge -/// -/// # Arguments -/// -/// * `params` - The KZG parameters -/// * `domain` - The domain for the polynomial -/// * `f_poly` - The polynomial to compute the opening proof for -/// * `y` - The challenge -/// * `z` - The value of the polynomial at the challenge -/// -/// # Returns -/// -/// * The KZG opening proof as a G1 point -pub fn create_naive_kzg_proof< - Scheme: CommitmentScheme, ->( - params: &ParamsKZG, - domain: &EvaluationDomain, - f_poly: &Polynomial<::Scalar, Coeff>, - y: Fp, - z: Fp, -) -> G1 { - let numerator = f_poly - z; - let mut t_y_vals = kate_division(&numerator.to_vec(), y); - // The resulting degree is one less than the degree of the numerator, so we need to pad it with zeros back to the original polynomial size - t_y_vals.resize(f_poly.len(), Fp::ZERO); - let t_y = domain.coeff_from_vec(t_y_vals); - commit_kzg(params, &t_y) -} - -/// Verify the naive KZG proof -/// J Thaler, Proofs, Arguments, and Zero-Knowledge, §15.2, eq. 15.2, p. 233 -/// e(c·g^(−z),g) = e(π,g^τ ·g^(−y)), y is the challenge -/// -/// # Arguments -/// -/// * `params` - The KZG parameters -/// * `c` - The commitment to the polynomial -/// * `pi` - The KZG opening proof -/// * `y` - The challenge -/// * `z` - The value of the polynomial at the challenge -/// -/// # Returns -/// -/// * True if the proof is valid, false otherwise -pub fn verify_kzg_proof(params: &ParamsKZG, c: G1, pi: G1, y: &Fp, z: &Fp) -> bool -where - G1Affine: PairingCurveAffine, -{ - let g_to_minus_z = G1Affine::generator() * &(-z); - let c_g_to_minus_z: G1 = c + g_to_minus_z; - let left_side = Bn256::pairing(&c_g_to_minus_z.to_affine(), &G2Affine::generator()); - - let g_to_minus_y = G2Affine::generator() * (-y); - let g_tau = params.s_g2(); - let g_tau_g_to_minus_y = g_tau + g_to_minus_y; - let right_side = Bn256::pairing(&pi.to_affine(), &g_tau_g_to_minus_y.to_affine()); - - left_side == right_side -} diff --git a/prover/src/utils/csv_parser.rs b/prover/src/utils/csv_parser.rs deleted file mode 100644 index 43b34895..00000000 --- a/prover/src/utils/csv_parser.rs +++ /dev/null @@ -1,74 +0,0 @@ -use num_bigint::BigUint; -use std::collections::HashMap; -use std::error::Error; -use std::fs::File; -use std::path::Path; - -use crate::cryptocurrency::Cryptocurrency; -use crate::entry::Entry; - -pub fn parse_csv_to_entries, const N_CURRENCIES: usize>( - path: P, - entries: &mut [Entry], - cryptocurrencies: &mut [Cryptocurrency], -) -> Result<(), Box> { - let file = File::open(path)?; - let mut rdr = csv::ReaderBuilder::new().from_reader(file); - - let headers = rdr.headers()?.clone(); - - // Extracting cryptocurrency names from column names - for (i, header) in headers.iter().skip(1).enumerate() { - if i >= cryptocurrencies.len() { - println!( - "Too many columns in the CSV file, expected {}, skipping the rest", - cryptocurrencies.len() - ); - break; - } - // Skipping 'username' column - let parts: Vec<&str> = header.split('_').collect(); - if parts.len() == 3 && parts[0] == "balance" { - cryptocurrencies[i] = Cryptocurrency { - name: parts[1].to_owned(), - chain: parts[2].to_owned(), - }; - } else { - // Throw an error if the header is malformed - return Err(format!("Invalid header: {}", header).into()); - } - } - - let mut balances_acc: Vec = vec![BigUint::from(0_usize); N_CURRENCIES]; - - for (i, result) in rdr.deserialize().enumerate() { - let record: HashMap = result?; - let username = record.get("username").ok_or("Username not found")?.clone(); - - let mut balances_big_int = Vec::new(); - for cryptocurrency in &mut *cryptocurrencies { - let balance_str = record - .get(format!("balance_{}_{}", cryptocurrency.name, cryptocurrency.chain).as_str()) - .ok_or(format!( - "Balance for {} on {} not found", - cryptocurrency.name, cryptocurrency.chain - ))?; - let balance = BigUint::parse_bytes(balance_str.as_bytes(), 10).ok_or(format!( - "Invalid balance for {} on {}", - cryptocurrency.name, cryptocurrency.chain - ))?; - balances_big_int.push(balance); - } - - balances_acc = balances_acc - .iter() - .zip(balances_big_int.iter()) - .map(|(x, y)| x + y) - .collect(); - - let entry = Entry::new(username, balances_big_int.try_into().unwrap())?; - entries[i] = entry; - } - - Ok(()) -} diff --git a/prover/src/utils/mod.rs b/prover/src/utils/mod.rs index 3cd0bfc8..06099b77 100644 --- a/prover/src/utils/mod.rs +++ b/prover/src/utils/mod.rs @@ -1,8 +1,5 @@ -pub mod amortized_kzg; -mod csv_parser; mod dummy_entries; mod operation_helpers; -pub use csv_parser::parse_csv_to_entries; pub use dummy_entries::generate_dummy_entries; pub use operation_helpers::*;